Jump to content

$LVN_KEYDOWN/$tagNMLVKEYDOWN does not work in 64 bit


Recommended Posts

On 7/13/2023 at 10:57 AM, Andreik said:

It should work well like this:

$tagNMHDR & ';align 4;word wVKey;align 2;uint Flags;'

 

I noticed the error in your definition as soon as you posted it.  I didn't immediately correct it because I thought that you would've caught and corrected it yourself.  For the record, the definition that you provided in your example script was correct.  I'm not sure why you thought the one with the additional "align" keywords was more correct. ;)

For both 32 & 64 bit, technically, yes, your suggested definition will work,  but that's only because the "Flags" field is not being referenced.  In this specific case, the first "align 4" is unnecessary and the second "align 2" is simply incorrect and should not be defined.  The DllStructCreate() function, in this specific case, will correctly pad and align the structs for both 32 & 64 bit without any additional alignment help (assuming the tags are defined correctly).

The short example below, will graphically show the misalignment issue in your definition and how the correct alignment & padding look. 

Note:
The only reason that I included a definition of the NMHDR struct in my example, instead of using the one included StructureConstants.au3, is that it is easier to understand when you can see the definition and I prefer to append ";" to the end of my struct tags/definitions because it makes the definition of structs within structs cleaner and easier to read.  Also, the first STRUCT and last ENDSTRUCT of my LVKEYDOWN tag are not technically needed because the DllStructCreate() function implicitly adds them, but I prefer to define them explicitly (as they appear in the actual C definition).

Example script:

#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d

#AutoIt3Wrapper_UseX64=y


#include <WinAPIDiag.au3>
#include <StructureConstants.au3>


Const $tag_NMHDR = _
    "struct;"              & _
    "  hwnd     hwndFrom;" & _
    "  uint_ptr idFrom;"   & _
    "  uint     code;"     & _
    "endstruct;"

Const $tag_LVKEYDOWN = _
    "struct;"          & _
       $tag_NMHDR      & _
    "  word   wVKey;"  & _
    "  uint   flags;"  & _
    "endstruct;"

Const $tag_LVKEYDOWN_Andreik = _
    $tag_NMHDR      & _
    "align 4;"      & _
    "word   wVKey;" & _
    "align 2;"      & _
    "uint   flags;"


_WinAPI_DisplayStruct(DllStructCreate($tag_LVKEYDOWN_Andreik), $tag_LVKEYDOWN_Andreik, "LVKEYDOWN - Andreik - " & (@AutoItX64 ? "64-bit" : "32-bit"))

_WinAPI_DisplayStruct(DllStructCreate($tag_LVKEYDOWN), $tag_LVKEYDOWN, "LVKEYDOWN - THEXMAN - " & (@AutoItX64 ? "64-bit" : "32-bit"))

Display of structs when run as 32-bit:

image.thumb.png.7d1a519f83819196490a4d24010291b9.png

Display of structs when run as 64-bit:

image.thumb.png.d3804c62da2821299b4f66cd67df7cc9.png

Although the subject of memory alignment and struct padding is outside the scope of AutoIt General Help & Support, if a more detailed explanation of why the struct padding and/or memory alignments are the way they are for both struct tag definitions, please feel free to ask.

Edited by TheXman
Link to comment
Share on other sites

Wrong defined in first post and then just copied (the sin of copy/paste). About the example it works fine because DllStructCreate() does some memory alignment, at least in the last versions of AutoIt. Align 4 is out of place, but you suggest that LVKEYDOWN doesn't need the 2 bytes align on previous AutoIt versions?

When the words fail... music speaks.

Link to comment
Share on other sites

1 hour ago, Andreik said:

you suggest that LVKEYDOWN doesn't need the 2 bytes align on previous AutoIt versions?

I haven't looked at any previous versions.  If the previous versions have the exact same definitions as the current version, then yes.  And if that is true, then it is probably because either no one caught the error or no one was using the "flags" field.  Also, much older versions would not be using the version  of NMHDR that has the UINT_PTR.  If I'm not mistaken, the new NMHDR definition was only implemented by Microsoft when the Windows Runtime API for UWP apps came into existence.  That is why there are conditional compilation directives in winuser.h for NMHDR.  commctrl.h still has the older definition.  WinUser.h has the new NMHDR struct defined within conditional directives based on a WINAPI_FAMILY_PARTITION macro.  That code came along for UWP because of the newer Window Runtime API set (as opposed to the Win32 API Set)

Edited by TheXman
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...