Jump to content

$LVN_KEYDOWN/$tagNMLVKEYDOWN does not work in 64 bit


Recommended Posts

Hi -

I need to trigger up/down in a ListView. My script does well in 32 bit, but compiling the script to 64 bit $LVN_KEYDOWN/$tagNMLVKEYDOWN doesn't work: "VKey" always returns 0. Here's a reproducer I've found ( https://www.autoitscript.com/forum/topic/165452-using-updown-in-listview/ ):

AutoIt3Wrapper_UseX64=Y


#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIListView.au3>

Global $bChanged = False

$hGUI = GUICreate("Test", 500, 500)

$cLV = GUICtrlCreateListView("Column 1", 10, 10, 200, 200)
$hLV = GUICtrlGetHandle($cLV)
For $i = 0 To 19
    GUICtrlCreateListViewItem("Item " & $i, $cLV)
Next

GUISetState()

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    If $bChanged Then
        $j = _GUICtrlListView_GetSelectedIndices($hLV)
        ConsoleWrite($j & @CRLF)
        $bChanged = False
    EndIf

WEnd

Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
    $hWndListView = $hLV

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_KEYDOWN
                    $tStruct = DllStructCreate($tagNMLVKEYDOWN, $lParam)
                    $iKey = DllStructGetData($tStruct, "VKey")
                    Switch $iKey
                        Case 38, 40 ; Up, Down
                            $bChanged = True
                    EndSwitch
                Case $NM_CLICK
                    $bChanged = True
            EndSwitch

    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Any chance to work around this issue?

Edited by supersonic
Link to comment
Share on other sites

Thank you -

In AutoIt V3.3.14.5 executing 'ConsoleWrite($tagNMLVKEYDOWN)' returns as follows:

32 bit - [align 1;struct;hwnd hWndFrom;uint_ptr IDFrom;INT Code;endstruct;word VKey;uint Flags]
64 bit - [align 1;struct;hwnd hWndFrom;uint_ptr IDFrom;INT Code;endstruct;word VKey;uint Flags]

So, is it still a bug? Is it worth to open another ticket?

Edited by supersonic
Link to comment
Share on other sites

Add this to top of _WM_NOTIFY function and it should work:

Local Const $tagNMLVKEYDOWN = $tagNMHDR & ";word VKey;uint Flags"

 

Link to comment
Share on other sites

  • Moderators

supersonic,

Yes.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • 1 year later...
On 7/26/2018 at 1:56 PM, LarsJ said:

Add this to top of _WM_NOTIFY function and it should work:

Local Const $tagNMLVKEYDOWN = $tagNMHDR & ";word VKey;uint Flags"

 

I struggled for hours before reading your post for my $LVN_KEYDOWN interception. Thanks !!

How have this not been solved until now ?

All the examples related in this forum don't work cause this. And this too for example : _GUICtrlListView_GetHotItem : when pressing keys, vKey stays at 0 and it's the Flag which points to an adress.

Can a mod explain me ?

Thanks 😊

Edited by JoeBar
Link to comment
Share on other sites

On 12/2/2019 at 4:20 PM, JoeBar said:

I struggled for hours before reading your post for my $LVN_KEYDOWN interception. Thanks !!

Well I invested many hours to understand the issue.  And I must tell it is not an obvious solution.  Larsj solution works but it is not perfect.  MSDN says that flags in the structure should be 0.  But in reality it is not the case, it changes at every key stroke (but I am still looking for the meaning of the flags).  So removing the align 1 (like Larsj proposed) will work till you want to use flags.  So if we really want to respect the real struct of the message it should be :

$tagNMLVKEYDOWN = "align 2;" & $tagNMHDR & ";" & (@AutoItX64 ? "uint;" : "") & "word VKey;uint Flags"

 

Link to comment
Share on other sites

Ok, so today I faced the same issue as Supersonic and JoeBar described above.
* A script using $tagNMLVKEYDOWN had no issue when run under AutoIt.exe on a Windows 32bits computer

* Today, for the 1st time, I did run the script on a "OS:WIN_8/ CPU:X64 OS:X64" computer, the console showing that Autoit3_x64.exe was running the script. $VK_RIGHT, $VK_LEFT, nothing happened when you pressed the right or left key in the listview : it's like both keys were dead !

* Here is a list of different $tagNMLVKEYDOWN strings, found here and there :
1) Official release AutoIt 3.3.14.5 - Include file StructureConstants.au3 (file dated 15 march 2018)

Global Const $tagNMLVKEYDOWN = "align 1;" & $tagNMHDR & ";word VKey;uint Flags"

2) LarsJ proposal (above) at top of _WM_NOTIFY function :

Local Const $tagNMLVKEYDOWN = $tagNMHDR & ";word VKey;uint Flags"

3) Nine proposal (above)

$tagNMLVKEYDOWN = "align 2;" & $tagNMHDR & ";" & (@AutoItX64 ? "uint;" : "") & "word VKey;uint Flags"

4) Beta release 3.3.15.1-1 found here - Include file StructureConstants.au3 (file dated 04 april 2018)

Global Const $tagNMLVKEYDOWN = $tagNMHDR & ";align 2;word VKey;uint Flags"

jpm wrote this at the end of the corresponding track ticket #1130, found there :
"It has been fixed for the next Beta on my birthday ..." which is April 4th (as openly indicated in his profile) and that's the same date of StructureConstants.au3 in the Beta release, well done jpm :thumbsup:

Structures #2 #3 #4 work fine on x64 (tested them all today) but for now I'll stick to jpm's structure #4 as it should be found in the include file of the next official release... if no further change happens. Also structure #4 seems ok on 32 bits computers (just tested)

So if any of you share on the Forum a script running fine on your x86 computer, where $tagNMLVKEYDOWN is found, please don't forget to add the amended structure of $tagNMLVKEYDOWN to make it compatible with x64 computers running your script, for example :

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    ...
     Case $LVN_KEYDOWN
        Local Static $tagNMLVKEYDOWN = $tagNMHDR & ";align 2;word VKey;uint Flags"
        ... = DllStructCreate($tagNMLVKEYDOWN, $lParam)

I hope Static is correct in this case, so $tagNMLVKEYDOWN won't need to be re-declared each time  WM_NOTIFY() is called. It seems even better to follow LarsJ's advice and place it at the very top of WM_NOTIFY() in case keypress notifications need to be checked at several places within WM_NOTIFY()

Please note that in the Beta file, changes done to $tagNMLVKEYDOWN have also been applied to $tagNMTCKEYDOWN and $tagNMTVKEYDOWN

Edited by pixelsearch
Link to comment
Share on other sites

  • 4 weeks later...
  • 3 years later...

Sorry to post again in this old thread, but I needed the mentioned structure again.

This time for a TreeView - and - because I used AutoIt 3.3.14.5 - ran into the same error AGAIN. 😉

I followed the thread to the end and have to note for AutoIt 3.3.16.1 that for '$tagNMLVKEYDOWN' or '$tagNMTVKEYDOWN' the following is defined:

Global Const $tagNMLVKEYDOWN = $tagNMHDR & ";align 2;word VKey;uint Flags"
Global Const $tagNMTVKEYDOWN = $tagNMHDR & ";align 2;word VKey;uint Flags"

Is this finally correct after all?

Or is:

$tagNMHDR & ";word VKey;align 2;uint Flags"

"more correct"? And if yes: Why resp. where can this be understood (e.g. MSDN)?

Edited by supersonic
Link to comment
Share on other sites

This code works fine on 3.3.16.1 and some alignment is done automatically.

#AutoIt3Wrapper_UseX64=y

Global $hMain, $hTree
Global Const $tagNMHDR = "struct;hwnd hWndFrom;uint_ptr IDFrom;INT Code;endstruct"

$hMain = GUICreate('TreeView', 400, 400)
$hTree = GUICtrlCreateTreeView(10, 10, 380, 380)
GUISetState(@SW_SHOW, $hMain)

GUIRegisterMsg(0x004E, 'WM_NOTIFY')


Do
Until GUIGetMsg() = -3

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    If HWnd($tNMHDR.hWndFrom) = GUICtrlGetHandle($hTree) And $tNMHDR.Code = 0xFFFFFE64 Then ; TVN_KEYDOWN
        Local $tTVKEYDOWN = DllStructCreate($tagNMHDR & ';word wVKey;uint Flags;', $lParam)
        ConsoleWrite(DllStructGetSize($tTVKEYDOWN) & @TAB & $tTVKEYDOWN.wVKey & @CRLF)
    EndIf
    Return 'GUI_RUNDEFMSG'
EndFunc

If 3.3.14.5 doesn't do any alignments, probably it should be something like that;

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

Anyway, I am not sure why StructureConstants.au3 define idFrom in NMHDR as uint_ptr when MSDN says clearly that it's a simple unsigned integer.  :huh:

When the words fail... music speaks.

Link to comment
Share on other sites

Link to comment
Share on other sites

1 hour ago, pixelsearch said:

@Andreik could you please indicate the link where MSDN says that idFrom in NMHDR is a simple unsigned integer ?

Because here is what I just read on MSDN, article NMHDR structure

 

 

typedef struct tagNMHDR {
  HWND     hwndFrom;
  UINT_PTR idFrom;
  UINT     code;
} NMHDR;

 

TheXman already answered this and I think it's pretty clear that a control identifier it's an integer. Looking at some macros in CommCtrl.h I saw that sometimes idFrom might be send to procedures as wparam which it's uint_ptr indeed but in fact could be cast safely as unsigned integer. However, not sure why it has to be that integer dependent on processor word size.

Edited by Andreik

When the words fail... music speaks.

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...