Jump to content



Photo

Trapping $NM_RETURN in a ListView via WM_NOTIFY


  • Please log in to reply
23 replies to this topic

#1 Spiff59

Spiff59

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,312 posts

Posted 31 October 2008 - 03:23 PM

I'm wanting to modify an existing ListView to trap pressing {ENTER} and treat it the same as an $NM_DBLCLK. I've found a few examples out in the forums, but none of them work, I can't seen to trap a ListView $NM_RETURN event via NM_NOTIFY. Trapping all the other events works great, but not the enter key. Has something changed in newer versions of Autoit that has made the examples not function?
Thanks.







#2 mmavipc

mmavipc

    Spammer!

  • Banned (NOT IN USE)
  • 287 posts

Posted 31 October 2008 - 05:57 PM

I'm wanting to modify an existing ListView to trap pressing {ENTER} and treat it the same as an $NM_DBLCLK. I've found a few examples out in the forums, but none of them work, I can't seen to trap a ListView $NM_RETURN event via NM_NOTIFY. Trapping all the other events works great, but not the enter key. Has something changed in newer versions of Autoit that has made the examples not function?
Thanks.

Can you post some of the examples?
Pure Au3 crypt funcs(I'm currently also working on making a dll from this)[Y] Be more active in the community[Y] Get 200 posts[N] Get 300 posts[N] Make a Topic in the example scripts forum with at least 50 replies.People who currently hate me:ValikSmOke_N

#3 Achilles

Achilles

    Achilles == Ichigo

  • Active Members
  • PipPipPipPipPipPip
  • 2,897 posts

Posted 31 October 2008 - 06:33 PM

I'm wanting to modify an existing ListView to trap pressing {ENTER} and treat it the same as an $NM_DBLCLK. I've found a few examples out in the forums, but none of them work, I can't seen to trap a ListView $NM_RETURN event via NM_NOTIFY. Trapping all the other events works great, but not the enter key. Has something changed in newer versions of Autoit that has made the examples not function?
Thanks.

I think that might actually be a bug with AutoIt. The example script for _GUICtrlListView_Create has the $NM_RETURN but it doesn't work.

#4 rasim

rasim

    Gray Scripter

  • Active Members
  • PipPipPipPipPipPip
  • 1,708 posts

Posted 01 November 2008 - 07:48 AM

Spiff59
After searching in the Google i think that this solution will be right:
AutoIt         
#include <GuiConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> #include <Constants.au3> Global Const $VK_RETURN = 0x0D ;Enter key $hGUI = GUICreate("Test GUI", 300, 200) $hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180) For $i = 1 To 10     _GUICtrlListView_AddItem($hListView, "Item " & $i) Next GUISetState() $wProcHandle = DllCallbackRegister("_WindowProc", "int", "hwnd;uint;wparam;lparam") $wProcOld = _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle)) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, $wProcOld) DllCallbackFree($wProcHandle) GUIDelete($hGui) Func _WindowProc($hWnd, $Msg, $wParam, $lParam)     Switch $hWnd         Case $hListView             Switch $Msg                 Case $WM_GETDLGCODE                     Switch $wParam                         Case $VK_RETURN                             ConsoleWrite("Enter key is pressed" & @LF)                             Return 0                     EndSwitch             EndSwitch     EndSwitch         Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $Msg, $wParam, $lParam) EndFunc

:mellow:
OS: Windows XP SP3, AutoIt version: 3.3.0.0Posted Image My Projects: Free_Resources | Splitter | wgetGUI | UnRARIt | USBMon | CDROM-Control | Volume Serial Changer | WinTrayPosted Image My UDFs: _ScreenSetting | ListView_Progress | ContextHelp | ToolTip_UDF | UnRAR | Zip32 | BassMod | ShellTreeView | GuiHotKey | 7ZipPosted Image My Examples: TrayIcon_Click | SystemTray_Refresh | _ListView_Sort | CPUmonLike above scripts? Please rate the topic Posted Image

#5 Spiff59

Spiff59

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,312 posts

Posted 02 November 2008 - 08:29 PM

That does seem to do the trick. Thanks, Rasim.
I'm not having any luck so far incorporating that into the WM_Notify routine, so that a single routine can process both the return character and mouse double-clicks from a ListView. But I am still trying...

#6 rasim

rasim

    Gray Scripter

  • Active Members
  • PipPipPipPipPipPip
  • 1,708 posts

Posted 03 November 2008 - 03:34 AM

Spiff59

so that a single routine can process both the return character and mouse double-clicks from a ListView

Example:
AutoIt         
#include <GuiConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> #include <Constants.au3> Global Const $VK_RETURN = 0x0D ;Enter key $hGUI = GUICreate("Test GUI", 300, 200) $hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180) For $i = 1 To 10     _GUICtrlListView_AddItem($hListView, "Item " & $i) Next GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() $wProcHandle = DllCallbackRegister("_WindowProc", "int", "hwnd;uint;wparam;lparam") $wProcOld = _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle)) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, $wProcOld) DllCallbackFree($wProcHandle) GUIDelete($hGui) Func _WindowProc($hWnd, $Msg, $wParam, $lParam)     Switch $hWnd         Case $hListView             Switch $Msg                 Case $WM_GETDLGCODE                     Switch $wParam                         Case $VK_RETURN                             ConsoleWrite("Enter key is pressed" & @LF)                             Return 0                     EndSwitch             EndSwitch     EndSwitch         Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $Msg, $wParam, $lParam) EndFunc Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)     Local $hWndListView, $tNMHDR, $hWndFrom, $iCode         $hWndListView = $hListView     If Not IsHWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($hListView)         $tNMHDR = DllStructCreate($tagNMHDR, $lParam)     $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))     $iCode = DllStructGetData($tNMHDR, "Code")         Switch $hWndFrom         Case $hWndListView             Switch $iCode                 Case $NM_DBLCLK                     ConsoleWrite("Double click!" & @LF)             EndSwitch     EndSwitch         Return $GUI_RUNDEFMSG EndFunc

:mellow:
OS: Windows XP SP3, AutoIt version: 3.3.0.0Posted Image My Projects: Free_Resources | Splitter | wgetGUI | UnRARIt | USBMon | CDROM-Control | Volume Serial Changer | WinTrayPosted Image My UDFs: _ScreenSetting | ListView_Progress | ContextHelp | ToolTip_UDF | UnRAR | Zip32 | BassMod | ShellTreeView | GuiHotKey | 7ZipPosted Image My Examples: TrayIcon_Click | SystemTray_Refresh | _ListView_Sort | CPUmonLike above scripts? Please rate the topic Posted Image

#7 Spiff59

Spiff59

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,312 posts

Posted 04 November 2008 - 05:33 PM

I guess both procedures can't be combined into one, but I could live with seperate procedures. But with this code, I can't seem to determine which line of the ListView was either clicked on or had the enter key pressed. GuiCtrlRead seems to be returning 0 in all cases.

#8 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 04 November 2008 - 07:29 PM

None of the built-in AutoIt GUI functions will work in the new window procedure of your subclassed control, since it's window procedure is no longer under AutoIt's "supervision". You'll have to use the _GuiCtrlListView_*** UDF functions in that window procedure.

Edited by wraithdu, 04 November 2008 - 07:30 PM.


#9 rasim

rasim

    Gray Scripter

  • Active Members
  • PipPipPipPipPipPip
  • 1,708 posts

Posted 05 November 2008 - 09:47 AM

Spiff59
AutoIt         
#include <GuiConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> #include <Constants.au3> Global Const $VK_RETURN = 0x0D ;Enter key $hGUI = GUICreate("Test GUI", 300, 200) $hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180) For $i = 1 To 10     _GUICtrlListView_AddItem($hListView, "Item " & $i) Next GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() $wProcHandle = DllCallbackRegister("_WindowProc", "int", "hwnd;uint;wparam;lparam") $wProcOld = _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle)) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, $wProcOld) DllCallbackFree($wProcHandle) GUIDelete($hGui) Func _WindowProc($hWnd, $Msg, $wParam, $lParam)     Switch $hWnd         Case $hListView             Switch $Msg                 Case $WM_GETDLGCODE                     Switch $wParam                         Case $VK_RETURN                             ConsoleWrite(_GUICtrlListView_GetItemText($hListView, _                                          _GUICtrlListView_GetSelectedIndices($hListView)) & @LF)                             Return 0                     EndSwitch             EndSwitch     EndSwitch         Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $Msg, $wParam, $lParam) EndFunc Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)     Local $hWndListView, $tNMHDR, $hWndFrom, $iCode         $hWndListView = $hListView     If Not IsHWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($hListView)         $tNMHDR = DllStructCreate($tagNMHDR, $lParam)     $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))     $iCode = DllStructGetData($tNMHDR, "Code")         Switch $hWndFrom         Case $hWndListView             Switch $iCode                 Case $NM_DBLCLK                     ConsoleWrite("Double click!" & @LF)             EndSwitch     EndSwitch         Return $GUI_RUNDEFMSG EndFunc

OS: Windows XP SP3, AutoIt version: 3.3.0.0Posted Image My Projects: Free_Resources | Splitter | wgetGUI | UnRARIt | USBMon | CDROM-Control | Volume Serial Changer | WinTrayPosted Image My UDFs: _ScreenSetting | ListView_Progress | ContextHelp | ToolTip_UDF | UnRAR | Zip32 | BassMod | ShellTreeView | GuiHotKey | 7ZipPosted Image My Examples: TrayIcon_Click | SystemTray_Refresh | _ListView_Sort | CPUmonLike above scripts? Please rate the topic Posted Image

#10 WeMartiansAreFriendly

WeMartiansAreFriendly

    Where's the kaboom?

  • Active Members
  • PipPipPipPipPipPip
  • 1,245 posts

Posted 12 March 2010 - 12:50 AM

@rasim, OP hasn't replied, but it works quite as advertised, I would def. prefer $NM_RETURN method though.


I think that might actually be a bug with AutoIt. The example script for _GUICtrlListView_Create has the $NM_RETURN but it doesn't work.


Do the devs know of this.. maybe you should file a bug report?

Edited by RockemSockem, 12 March 2010 - 12:53 AM.

Posted ImageDon't bother, It's inside your monitor!------GUISetOnEvent should behave more like HotKeySet()

#11 drever44

drever44

    Seeker

  • Active Members
  • 20 posts

Posted 10 March 2011 - 09:53 PM

$NM_RETURN is very disappointing.

this seams to have been a problem for some time now, so i don’t suppose that it will be corrected any time soon, looked for a work around for several hours and found nothing that will work correctly with my script.
after putting all this time into my project and only to find out that i cant use the enter key on a list-view is overwhelmingly sad. is there possibly a UDF out there that will correct this issue or am i just not seeing this correctly. perhaps in the bata version this will be corrected.

Simply want to left click an item in the list-view and hit return to open an edit window/gui how hard can that be.
and also having a little trouble with double left click and left click defined at the same time. no mater how fast you double click left click always happens. is this not possible also same with right click and double right click. if not i can live with out the doubles.

any help would be greatly appreciated

#12 major4579

major4579

    Seeker

  • Active Members
  • 5 posts

Posted 26 March 2011 - 02:24 PM

$NM_RETURN is very disappointing.

this seams to have been a problem for some time now, so i don’t suppose that it will be corrected any time soon, looked for a work around for several hours and found nothing that will work correctly with my script.
after putting all this time into my project and only to find out that i cant use the enter key on a list-view is overwhelmingly sad. is there possibly a UDF out there that will correct this issue or am i just not seeing this correctly. perhaps in the bata version this will be corrected.

Simply want to left click an item in the list-view and hit return to open an edit window/gui how hard can that be.
and also having a little trouble with double left click and left click defined at the same time. no mater how fast you double click left click always happens. is this not possible also same with right click and double right click. if not i can live with out the doubles.

any help would be greatly appreciated


I am using a different approach (probably has it's own problems.. be kind), This is combined with the Double-Click trap mentioned previously. Basically $fDblClk is set to true if an item is Double-Clicked or selected with the Enter key.

Plain Text         
    GUISetState()         HotKeySet ('{Enter}', '_Enter_Pressed')         While 1         Switch GUIGetMsg()             Case $_GUI_EVENT_CLOSE                 $Selected = -1                 ExitLoop             Case $hExit                 $Selected = -1                 ExitLoop             EndSwitch         If ($fDblClk = True) Then ; If Item is Double-Clicked -or- ENTERed             For $i = 0 To GUICtrlSendMsg($hListView, $_LVM_GETITEMCOUNT, 0, 0)                 If GUICtrlSendMsg($hListView, $_LVM_GETITEMSTATE, $i, 0x2) Then                     $Selected = $i                     EndIf                 Next             $fDblClk = False             ExitLoop             Endif         WEnd     GUIDelete($hGUI)     HotKeySet ('{Enter}')     Return $Selected EndFunc   ;==>_ArrayDisplay Func _Enter_Pressed()     $fDblClk = True     Return     EndFunc


#13 Jayson

Jayson

    Prodigy

  • Active Members
  • PipPipPip
  • 165 posts

Posted 28 March 2011 - 08:36 PM

@drever44 : I made this script some time ago (with some help) and maybe you can make a work around with this. Double click an item so you can edit it and then press enter.

Plain Text         
#include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> #include <Misc.au3> Global $aLV_Click_Info, $hTmp_Edit = 0, $fDblClk = False $hGUI = GUICreate("Test GUI", 300, 200) $hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180) For $i = 1 To 10     _GUICtrlListView_AddItem($hListView, "Item " & $i)     _GUICtrlListView_AddSubItem($hListView, $i - 1, "SubItems" & $i, 1) Next GUISetState() GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") While 1     If $hTmp_Edit <> 0 Then ; If a temporary edit exists         If _IsPressed("0D") Then ; If ENTER pressed             $sText = GUICtrlRead($hTmp_Edit) ; Set label to edit content             _GUICtrlListView_SetItemText($hListView, $aLV_Click_Info[0], $sText, $aLV_Click_Info[1])             GUICtrlDelete($hTmp_Edit) ; Delete temporary edit             $hTmp_Edit = 0         EndIf     EndIf     If $fDblClk Then ; If an item was double clicked         $fDblClk = False         GUICtrlDelete($hTmp_Edit) ; Delete any existing temporary edits         $sTmp_Text = _GUICtrlListView_GetItemText($hListView, $aLV_Click_Info[0], $aLV_Click_Info[1]) ; Read current text of clicked label         Switch $aLV_Click_Info[1] ; Get label position             Case 0 ; On Item                 $aLV_Rect_Info = _GUICtrlListView_GetItemRect($hListView, $aLV_Click_Info[0], 2)             Case Else ; On SubItem                 $aLV_Rect_Info = _GUICtrlListView_GetSubItemRect($hListView, $aLV_Click_Info[0], $aLV_Click_Info[1])             EndSwitch         $hTmp_Edit = GUICtrlCreateEdit($sTmp_Text, $aLV_Rect_Info[0] + 13, $aLV_Rect_Info[1] + 10, $aLV_Rect_Info[2] - $aLV_Rect_Info[0], $aLV_Rect_Info[3] - $aLV_Rect_Info[1], 0) ; Create temporary edit         GUICtrlSetState($hTmp_Edit, $GUI_FOCUS)     EndIf WEnd Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)     Local $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)     Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))     Local $iCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hListView             Switch $iCode                 Case $NM_DBLCLK                     $aLV_Click_Info = _GUICtrlListView_SubItemHitTest($hListView)                     If $aLV_Click_Info[0] <> -1 Then $fDblClk = True             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY

Edited by Jayson, 28 March 2011 - 08:46 PM.


#14 Hawk

Hawk

    Seeker

  • Active Members
  • 32 posts

Posted 08 February 2012 - 09:22 PM

@rasim, OP hasn't replied, but it works quite as advertised, I would def. prefer $NM_RETURN method though.



I'm wanting to modify an existing ListView to trap pressing {ENTER} and treat it the same as an $NM_DBLCLK. I've found a few examples out in the forums, but none of them work, I can't seen to trap a ListView $NM_RETURN event via NM_NOTIFY. Trapping all the other events works great, but not the enter key. Has something changed in newer versions of Autoit that has made the examples not function?
Thanks.

I think that might actually be a bug with AutoIt. The example script for _GUICtrlListView_Create has the $NM_RETURN but it doesn't work.


Do the devs know of this.. maybe you should file a bug report?


Sorry for digging out such an old thread, but here is the problem exactly written down already. The $NM_RETURN trap seems to not work at all. In my program it just didn't work, so I tried the _GUICtrlListView_Create example script and there it also just doesn't respond to pressing the return key.

#15 Melba23

Melba23

    Yes, me!

  • Moderators
  • 15,383 posts

Posted 08 February 2012 - 09:47 PM

Hawk,

Hello again - keeping me busy this evening! ;)

Use an Accelerator key and a flag like this: ;)
AutoIt         
#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GUIListView.au3> Global $fDbl_Click = False, $hListView Example_UDF_Created() Func Example_UDF_Created()     Local $GUI, $sHeader = "Full header of any width at all"     $GUI = GUICreate("(UDF Created) ListView Get Item Param", 400, 300)     $hListView = _GUICtrlListView_Create($GUI, "", 2, 2, 394, 268)     ConsoleWrite($hListView & @CRLF)     _GUICtrlListView_AddColumn($hListView, $sHeader)     _GUICtrlListView_AddColumn($hListView, "")     ; Add items     _GUICtrlListView_AddItem($hListView, "Item 1")     _GUICtrlListView_AddItem($hListView, "Item 2")     _GUICtrlListView_AddItem($hListView, "Item 3")     _GUICtrlListView_SetColumnWidth($hListView, 0, $LVSCW_AUTOSIZE_USEHEADER)     _GUICtrlListView_SetColumnWidth($hListView, 1, 0)     Local $hDummy = GUICtrlCreateDummy() ; <<<<<<<<<<<<<<<<<<<<<<<<<<     GUISetState()     Local $aAccelKeys[1][2] = [["{ENTER}", $hDummy]]     GUISetAccelerators($aAccelKeys)     GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")     While 1         Switch GUIGetMsg()             Case $GUI_EVENT_CLOSE                 Exit             Case $hDummy ; <<<<<<<<<<<<<<<<<<<<<<<<<<                 $iIndex = _GUICtrlListView_GetSelectedIndices($hListView)                 $fDbl_Click = $iIndex         EndSwitch         If $fDbl_Click Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<             $sText = _GUICtrlListView_GetItemText($hListView, $fDbl_Click)             MsgBox(0, "Hi", "You either double-clicked or" & @CRLF & "you pressed 'Enter'" & @CRLF & "on " & $sText)             $fDbl_Click = False         EndIf     WEnd     GUIDelete() EndFunc   ;==>Example_UDF_Created Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)     #forceref $hWnd, $iMsg, $iwParam     $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)     $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))     $iCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hListView             Switch $iCode                 Case $NM_DBLCLK                     $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)                     $fDbl_Click = DllStructGetData($tInfo, "Index")             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY

Please ask if anything is not clear. :)

M23
StringSize - Automatically size controls to fit text - ExtMsgBox - A user customisable replacement for MsgBox

Toast - Small GUIs which pop out of the Systray - Marquee - Scrolling tickertape GUIs

Scrollbars - Automatically sized scrollbars with a single command - GUIFrame - Subdivide GUIs into many adjustable frames

GUIExtender - Extend and retract multiple sections within a GUI - NoFocusLines - Remove the dotted focus lines from buttons, sliders, radios and checkboxes

ChooseFileFolder - Single and multiple selections from specified path tree structure - - Notify - Small notifications on the edge of the display

RecFileListToArray - An alternative to _FileListToArray with user-defined include/exclude masks, maximum recursion level, sorting and displayed path options

GUIListViewEx - Insert, delete, move, drag and sort ListView items


#16 Yashied

Yashied

    Happy in Moscow

  • MVPs
  • 2,512 posts

Posted 08 February 2012 - 10:57 PM

In order to use the return key in ListView, you must replace its default WindowProc procedure as follows.

Func _WindowProc($hWnd, $iMsg, $wParam, $lParam)     Switch $iMsg         Case $WM_GETDLGCODE             Switch $wParam                 Case $VK_RETURN                     Return $DLGC_WANTALLKEYS             EndSwitch     EndSwitch     Return _WinAPI_CallWindowProc($pDefWindowProc, $hWnd, $iMsg, $wParam, $lParam) EndFunc   ;==>_WindowProc


But unfortunately DllCallbackRegister() will not work properly here. But you can write your own DLL.

Global Comctl32.l = OpenLibrary(#PB_Any, "comctl32.dll") ProcedureDLL.i SubclassProc(*HWnd, Msg.l, *WParam, *LParam, *ID, *IParam)     Select Msg         Case #WM_GETDLGCODE             Select *WParam                 Case #VK_RETURN                     ProcedureReturn #DLGC_WANTALLKEYS             EndSelect     EndSelect     ProcedureReturn CallFunction(Comctl32, "DefSubclassProc", *HWnd, Msg, *WParam, *LParam) EndProcedure


Attached File  WSP.dll   5.5K   53 downloads

And a simple example.

AutoIt         
#Include <APIConstants.au3> #Include <GUIListView.au3> #Include <GUIConstantsEx.au3> #Include <ListViewConstants.au3> #Include <WinAPIEx.au3> OnAutoItExitRegister('AutoItExit') $hForm = GUICreate('MyGUI', 300, 300) $hLV = GUICtrlGetHandle(GUICtrlCreateListView('Name', 0, 0, 300, 300, -1, 0)) For $i = 1 To 4     _GUICtrlListView_AddItem($hLV, 'Item' & $i) Next $hDll = _WinAPI_LoadLibrary(@ScriptDir & 'WSP.dll') If $hDll Then     $pSubclassProc = _WinAPI_GetProcAddress($hDll, 'SubclassProc')     If Not @error Then         _WinAPI_SetWindowSubclass($hLV, $pSubclassProc, 1000)     Else         _WinAPI_FreeLibrary($hDll)     EndIf EndIf $Dummy = GUIctrlCreateDummy() GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY') GUISetState() While 1     Switch GUIGetMsg()         Case 0             ContinueLoop         Case $GUI_EVENT_CLOSE             Exit         Case $Dummy             MsgBox(0, '', _GUICtrlListView_GetItemText($hLV, GUICtrlRead($Dummy)) & ' is activated.')     EndSwitch WEnd Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)     Local $tNMIA = DllStructCreate($tagNMITEMACTIVATE, $lParam)     Local $hTarget = DllStructGetData($tNMIA, 'hWndFrom')     Local $ID = DllStructGetData($tNMIA, 'Code')     Switch $hTarget         Case $hLV             Switch $ID                 Case $LVN_ITEMACTIVATE                     Local $Item = DllStructGetData($tNMIA, 'Index')                     If _GUICtrlListView_GetItemSelected($hLV, $Item) Then                         GUICtrlSendToDummy($Dummy, $Item)                     EndIf             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY Func AutoItExit()     If $pSubclassProc Then         _WinAPI_RemoveWindowSubclass($hLV, $pSubclassProc, 1000)     EndIf EndFunc   ;==>AutoItExit


@Melba23

Yes it works, but it has several drawbacks:
  • _GUICtrlListView_GetSelectedIndices() may be too slow for a large number of items.
  • You should check the current focus.


#17 Hawk

Hawk

    Seeker

  • Active Members
  • 32 posts

Posted 10 February 2012 - 04:29 PM

Thanks to you two for your input, I am thinking of which method to implement.

@Melba23: I get the idea and can use this. I am just figuring out, how to use this with a $BS_DEFPUSHBUTTON-style button that reacts in all my GUI to pressing ENTER. As it seems, the accelerator catches the ENTER key and does not allow the other msges connected with pressing it to be sent. But I think I can send that message to the default push button within $hDummy as a workaround. As soon as I have time I will work on that.
Edit: As I write this, the idea came to me that because I track every ENTER keytroke anyways due to the default pushbutton, I can just add checks in that buttons script to check if the listview has focus and if items are selected. Then I can just do what I intended with the listview items as well as what I wanted with the button. Will check that method soon when I find time.

@Yashied: Your method works flawlessly, I just wanted to have an executable file without additional DLLs. So I tried to figure out why it doesn't work with code implementation and failed. I didn't understand:
1) How would DllCallbackRegister() work here anyways? I think it can only be used when you call DLL functions manually, like with DllCall.
2) _WinAPI_GetProcAddress() just returns an address if I am right. So how does _WinAPI_SetWindowSubclass() know to take the function at pointer $pSubClassProc IN WSP.dll and not from any other DLL? Or does _WinAPI_GetProcAddress() return more than just a number?

Is it the only way to change the callback function of listviews?

TIA,
Hawk

Edited by Hawk, 10 February 2012 - 09:10 PM.


#18 Melba23

Melba23

    Yes, me!

  • Moderators
  • 15,383 posts

Posted 10 February 2012 - 05:01 PM

Hawk,

Here is an amended script which solves your BS_DEFPUSHBUTTON problem and also addresses Yashied's comment about requiring focus on the ListView:
AutoIt         
#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <GUIListView.au3> #include <WinAPI.au3> Global $hListView, $hDummy Example_UDF_Created() Func Example_UDF_Created()     Local $GUI, $sHeader = "Full header of any width at all"     $GUI = GUICreate("Test", 400, 300)     $hListView = _GUICtrlListView_Create($GUI, "", 10, 10, 200, 200)     ConsoleWrite($hListView & @CRLF)     _GUICtrlListView_AddColumn($hListView, $sHeader)     _GUICtrlListView_AddColumn($hListView, "")     ; Add items     _GUICtrlListView_AddItem($hListView, "Item 1")     _GUICtrlListView_AddItem($hListView, "Item 2")     _GUICtrlListView_AddItem($hListView, "Item 3")     _GUICtrlListView_SetColumnWidth($hListView, 0, $LVSCW_AUTOSIZE_USEHEADER)     _GUICtrlListView_SetColumnWidth($hListView, 1, 0)     $hDummy = GUICtrlCreateDummy()     Local $hButton = GUICtrlCreateButton("Test", 10, 260, 80, 30, $BS_DEFPUSHBUTTON) ; <<<<<<<<<<<<<<<<<<<<<<<<<<     GUISetState()     GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")     While 1         Switch GUIGetMsg()             Case $GUI_EVENT_CLOSE                 Exit             Case $hButton                 If _WinAPI_GetFocus() = $hListView Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<                     ; Move to next section                     ContinueCase ; <<<<<<<<<<<<<<<<<<<<<<<<<<                 Else                     ; Action the DEFPUSHBUTTON                     MsgBox(0, "Aha", "Button pressed") ; <<<<<<<<<<<<<<<<<<<<<<<<<<                 EndIf             Case $hDummy                 ; We get here if the handler fired the control or if the ListView had focus when enter was pressed                 $iIndex = _GUICtrlListView_GetSelectedIndices($hListView)                 $sText = "Selected in ListView : " & _GUICtrlListView_GetItemText($hListView, $iIndex)                 MsgBox(0, "Hi", $sText)                 ; Reset focus away from listview                 GUICtrlSetState($hButton, $GUI_FOCUS)         EndSwitch     WEnd     GUIDelete() EndFunc   ;==>Example_UDF_Created Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)     #forceref $hWnd, $iMsg, $iwParam     $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)     $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))     $iCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hListView             Switch $iCode                 Case $NM_DBLCLK                     $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)                     ; Fire dummy control                     GUICtrlSendToDummy($hDummy)             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY

Please ask if you have any questions. :)

M23
StringSize - Automatically size controls to fit text - ExtMsgBox - A user customisable replacement for MsgBox

Toast - Small GUIs which pop out of the Systray - Marquee - Scrolling tickertape GUIs

Scrollbars - Automatically sized scrollbars with a single command - GUIFrame - Subdivide GUIs into many adjustable frames

GUIExtender - Extend and retract multiple sections within a GUI - NoFocusLines - Remove the dotted focus lines from buttons, sliders, radios and checkboxes

ChooseFileFolder - Single and multiple selections from specified path tree structure - - Notify - Small notifications on the edge of the display

RecFileListToArray - An alternative to _FileListToArray with user-defined include/exclude masks, maximum recursion level, sorting and displayed path options

GUIListViewEx - Insert, delete, move, drag and sort ListView items


#19 Hawk

Hawk

    Seeker

  • Active Members
  • 32 posts

Posted 15 February 2012 - 01:58 AM

It seems that trapping $NM_DBLCLK is not necessary because after double clicking we will receive a $LVN_ITEMACTIVATE notification anyways.
Is there a way to _SendMessage() this notification upon pressing ENTER?

I fiddled around with it and googled quite long about it but only made the script crash.

_SendMessage(?, $WM_NOTIFY, wparam, lparam, 0, "wparam", "lparam") is the puzzle.
Puzzle pieces amongst others are:
GUICtrlGetHandle($GUI) or $GUI
GUICtrlGetHandle($hListView) or $hListView
$LVN_ITEMACTIVATE

Edited by Hawk, 15 February 2012 - 03:12 AM.


#20 Yashied

Yashied

    Happy in Moscow

  • MVPs
  • 2,512 posts

Posted 15 February 2012 - 06:59 AM

AutoIt         
#Include <APIConstants.au3> #Include <GUIListView.au3> #Include <GUIConstantsEx.au3> #Include <ListViewConstants.au3> #Include <WinAPIEx.au3> Opt('MustDeclareVars', 1) Global $Accel[1][2] = [['{ENTER}', 0]] Global $hForm, $hLV, $Dummy Global $Item = -1 $hForm = GUICreate('MyGUI', 300, 300) $hLV = GUICtrlGetHandle(GUICtrlCreateListView('Name', 0, 0, 300, 300, -1, 0)) For $i = 1 To 4     _GUICtrlListView_AddItem($hLV, 'Item' & $i) Next $Dummy = GUIctrlCreateDummy() $Accel[0][1] = GUIctrlCreateDummy() GUISetAccelerators($Accel) GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY') GUISetState() While 1     Switch GUIGetMsg()         Case 0             ContinueLoop         Case $GUI_EVENT_CLOSE             Exit         Case $Dummy             MsgBox(0, '', _GUICtrlListView_GetItemText($hLV, GUICtrlRead($Dummy)) & ' is activated.')         Case $Accel[0][1]             Switch _WinAPI_GetFocus()                 Case 0                 Case $hLV                     If (Not _SCAW()) And ($Item <> -1) Then                         GUICtrlSendToDummy($Dummy, $Item)                     EndIf                     ContinueCase             EndSwitch             GUISetAccelerators(0, $hForm)             Send('{ENTER}')             GUISetAccelerators($Accel, $hForm)         Case Else     EndSwitch WEnd Func _SCAW()     Local $aData[5] = [0x10, 0x11, 0x12, 0x5B, 0x5C]     Local $tData = _WinAPI_GetKeyboardState()     If Not @error Then         For $i = 0 To 4             If BitAND(DllStructGetData($tData, 1, $aData[$i] + 1), 0xF0) Then                 Return $aData[$i]             EndIf         Next     EndIf     Return 0 EndFunc   ;==>_SCAW Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)     Static $Flag = False     Local $tNMIA = DllStructCreate($tagNMITEMACTIVATE, $lParam)     Local $hTarget = DllStructGetData($tNMIA, 'hWndFrom')     Local $ID = DllStructGetData($tNMIA, 'Code')     Switch $hWnd         Case 0         Case $hForm             Switch $hTarget                 Case $hLV                     Switch $ID                         Case $LVN_BEGINDRAG                             Return 0                         Case $LVN_ITEMACTIVATE                             GUICtrlSendToDummy($Dummy, DllStructGetData($tNMIA, 'Index'))                         Case $LVN_ITEMCHANGED                             If (BitAND(DllStructGetData($tNMIA, 'Changed'), $LVIF_STATE)) And (BitXOR(DllStructGetData($tNMIA, 'NewState'), DllStructGetData($tNMIA, 'OldState'))) Then                                 If BitAND(DllStructGetData($tNMIA, 'NewState'), $LVIS_SELECTED) Then                                     $Item = DllStructGetData($tNMIA, 'Index')                                     $Flag = 0                                 Else                                     If BitAND(DllStructGetData($tNMIA, 'OldState'), $LVIS_FOCUSED) Then                                         $Flag = 1                                     Else                                         If Not $Flag Then                                             $Item = -1                                         EndIf                                         $Flag = 0                                     EndIf                                 EndIf                             EndIf                         Case $NM_CLICK, $NM_DBLCLK, $NM_RCLICK, $NM_RDBLCLK                             Return 0                     EndSwitch             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users