littlebigman Posted June 6, 2023 Share Posted June 6, 2023 (edited) To catch a double-click on a plain list (not a listview), is a GUIRegisterMsg() + WM_COMMAND() required, or can it be done more simply within the while loop? While True $nMsg = GUIGetMsg() Switch $nMsg ;how to catch double-clicks? Case $List1 ConsoleWrite("Clicked on listbox: " & GUICtrlRead($List1)& @CRLF) Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd --- Edit: It misses some double-clicks. Am I doing it wrong? expandcollapse popup#include <GDIPlus.au3> #include <File.au3> #include <GDIPlus.au3> #include <Math.au3> #include <GUIConstantsEx.au3> #include <ListViewConstants.au3> #include <GUIListBox.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("Form1", 623, 449, 279, 114) $List1 = GUICtrlCreateList("", 0, 52, 622, 396) $Label1 = GUICtrlCreateLabel("Label1", 8, 8, 428, 31) GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") Global $DoubleClicked = Null GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg Local $hWndFrom, $iIDFrom, $iCode, $hWndListBox If Not IsHWnd($List1) Then $hWndListBox = GUICtrlGetHandle($List1) $hWndFrom = $ilParam $iIDFrom = BitAND($iwParam, 0xFFFF) $iCode = BitShift($iwParam, 16) Switch $hWndFrom Case $hWndListBox Switch $iCode Case $LBN_DBLCLK If Not $DoubleClicked Then $DoubleClicked = 1 EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc While True $nMsg = GUIGetMsg() Switch $nMsg Case $List1 ;ConsoleWrite("Clicked on listbox: " & GUICtrlRead($List1)& @CRLF) If $DoubleClicked Then $filename = GUICtrlRead($List1) ConsoleWrite("Double Clicked! " & $filename & @CRLF) ;Fails if filename contains spaces RunWait(@comspec & ' /c start ' & $filename, '', @SW_HIDE) $DoubleClicked = 0 EndIf Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Edited June 6, 2023 by littlebigman Link to comment Share on other sites More sharing options...
littlebigman Posted June 7, 2023 Author Share Posted June 7, 2023 (edited) From what I can tell, it misinterprets the very first double-click a single click, and when, later, single-clicking, it reports the first one as a double-click: Edit: Could it be the GUI loop is called before the WM_COMMAND function, making the "If $DoubleClicked" test unreliable? Edit: Apparently, it's not a good idead to mix code in the GUI loop and the WM_COMMAND function. taiete's code above works OK. expandcollapse popup#include <WindowsConstants.au3> #include <GUIListBox.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("Form1", 623, 449, 279, 114) $List1 = GUICtrlCreateList("", 0, 52, 622, 396) GUISetState(@SW_SHOW) GUIRegisterMsg($WM_COMMAND, "WM_COMMAND"); Needed to handle double-click on list widget Global $DoubleClicked = False ;Used to know if user double-clicked #EndRegion ### END Koda GUI section ### Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg Local $hWndFrom, $iIDFrom, $iCode, $hWndListBox If Not IsHWnd($List1) Then $hWndListBox = GUICtrlGetHandle($List1); BUG? What if $List1 IS a handle? $hWndFrom = $ilParam $iIDFrom = BitAND($iwParam, 0xFFFF) $iCode = BitShift($iwParam, 16) Switch $hWndFrom Case $hWndListBox Switch $iCode Case $LBN_DBLCLK If Not $DoubleClicked Then $DoubleClicked = True EndSwitch EndSwitch Return $GUI_RUNDEFMSG ;Makes no difference EndFunc GUICtrlSetData($List1, "item1") GUICtrlSetData($List1, "item2") While True $nMsg = GUIGetMsg() Switch $nMsg Case $List1 If $DoubleClicked Then ConsoleWrite("Double Clicked ") $DoubleClicked = False Else ConsoleWrite("Single click ") EndIf ConsoleWrite(GUICtrlRead($List1) & @CRLF) Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd Edited June 7, 2023 by littlebigman Link to comment Share on other sites More sharing options...
Solution robertocm Posted June 11, 2023 Solution Share Posted June 11, 2023 (edited) taietel code adapted for two ListBoxes expandcollapse popup#include <GUIConstantsEx.au3> #include <GUIListBox.au3> #include <WindowsConstants.au3> GUICreate("Form1", 400, 350) $hListBox = GUICtrlCreateList("", 5, 5, 190, 340) Local $t For $i=1 To 10 $t &="Item no."&$i&"|" Next GUICtrlSetData(-1,$t) $mnuLBContext = GUICtrlCreateContextMenu($hListBox) GUICtrlCreateMenuItem("MenuItem3", $mnuLBContext) GUICtrlCreateMenuItem("MenuItem2", $mnuLBContext) GUICtrlCreateMenuItem("MenuItem1", $mnuLBContext) GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") $hListBox_2 = GUICtrlCreateList("", 205, 5, 190, 340) GUICtrlSetData(-1,$t) GUISetState(@SW_SHOW) While 1 Sleep(10) Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg Local $hWndFrom, $iIDFrom, $iCode, $hWndListBox, $hWndListBox_2 If Not IsHWnd($hListBox) Then $hWndListBox = GUICtrlGetHandle($hListBox) If Not IsHWnd($hListBox_2) Then $hWndListBox_2 = GUICtrlGetHandle($hListBox_2) $hWndFrom = $ilParam $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word $iCode = BitShift($iwParam, 16) ; Hi Word Switch $hWndFrom Case $hListBox, $hWndListBox, $hListBox_2, $hWndListBox_2 Switch $iCode Case $LBN_DBLCLK ; Sent when the user double-clicks a string in a list box Switch $iIDFrom Case $hListBox, $hWndListBox ConsoleWrite("ListBox 1 Item " & _GUICtrlListBox_GetCurSel($hListBox) & @CRLF) Case $hListBox_2, $hWndListBox_2 ConsoleWrite("ListBox 2 Item " & _GUICtrlListBox_GetCurSel($hListBox_2) & @CRLF) EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_COMMAND Edited June 12, 2023 by robertocm Link to comment Share on other sites More sharing options...
littlebigman Posted June 22, 2023 Author Share Posted June 22, 2023 (edited) Thanks. Too bad catching double-clicks on a list requires handling messages outside the GUi loop. -- Edit: Out of curiosity, what's the difference between $WM_COMMAND and $WM_NOTIFY, and which function is recommended to handle double-clicks on a list? expandcollapse popupGUIRegisterMsg($WM_COMMAND, "WM_COMMAND"); Needed to handle double-click on list widget GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ;this allows you to capture all window messages. Global $DoubleClicked = False Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam ;there are a lot of window messages and they fire all the time. ;We'll need to filter the ones we want. Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) ;this should give us the handle of the control that triggered the event. $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $List1 ;Only react to messages from the $List1 Switch $iCode ;check the type of message Case $LBN_DBLCLK ;double click message ConsoleWrite("In WM_NOTIFY, double-click" & @CRLF) EndSwitch EndSwitch ; if you don't return $GUI_RUNDEFMSG, or 0 the rest of the messages won't be handles as they should. Return $GUI_RUNDEFMSG EndFunc Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg Local $hWndFrom, $iIDFrom, $iCode, $hWndListBox If Not IsHWnd($List1) Then $hWndListBox = GUICtrlGetHandle($List1); BUG? $hWndFrom = $ilParam $iIDFrom = BitAND($iwParam, 0xFFFF) $iCode = BitShift($iwParam, 16) Switch $hWndFrom Case $hWndListBox Switch $iCode Case $LBN_DBLCLK If Not $DoubleClicked Then $DoubleClicked = True EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc Edited June 22, 2023 by littlebigman Link to comment Share on other sites More sharing options...
Andreik Posted June 22, 2023 Share Posted June 22, 2023 WM_NOTIFY is a code sent by a control to its parent window when an event has occurred or the control requires some information, so accordingly wParam will contain identifier of the control sending the message and lParam is a pointer to a NMHDR structure that contains additional information. WM_COMMAND is a code sent when the user selects a command item from a menu, when a control sends a notification message to its parent window, or when an accelerator keystroke is translate, so accordingly when the message is sent by a control wParam high word will contain the control-defined notification code, wParam low word will contain the control identifier and lPara will contain the handle to the control window. There is no better, each is used when it's appropriate. If you are interested just to know when a control is click, both can give you the answer but is you are looking for additional information WM_NOTIFY will provide such details. littlebigman 1 When the words fail... music speaks. Link to comment Share on other sites More sharing options...
littlebigman Posted June 22, 2023 Author Share Posted June 22, 2023 Thanks. For some reason, I can't get the text of the selected item that I double-clicked in the listbox. Could it be because it's read in a WM_COMMAND section? expandcollapse popup#include <GUIConstantsEx.au3> #include <GUIListBox.au3> #include <WindowsConstants.au3> #include <array.au3> #Region GUICreate("Form1", 200, 350) $hListBox = GUICtrlCreateList("", 5, 5, 190, 340) GUICtrlSetData($hListBox,"item1|item2") #EndRegion GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") GUISetState(@SW_SHOW) ;in GUI loop, don't refer to listbox, or double-clicks won't be properly handled While True Sleep(10) Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg Local $hWndFrom, $iIDFrom, $iCode, $hWndListBox If Not IsHWnd($hListBox) Then $hWndListBox = GUICtrlGetHandle($hListBox) $hWndFrom = $ilParam $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word $iCode = BitShift($iwParam, 16) ; Hi Word Switch $hWndFrom Case $hListBox, $hWndListBox Switch $iCode Case $LBN_DBLCLK ; Sent when the user double-clicks a string in a list box ;BAD: Returns an array ConsoleWrite("Item "& _GUICtrlListBox_GetCurSel($hListBox)&@CRLF) ;NO CHANGE Local $selItems = _GUICtrlListBox_GetSelItemsText($hWndListBox) Local $selItems = _GUICtrlListBox_GetSelItemsText($hListBox) ConsoleWrite("Array size: " & UBound($selItems) & @CRLF) ConsoleWrite("Number of items: " & $selItems[0] & @CRLF) ConsoleWrite("Array: " & $selItems & @CRLF) ;BLOCKS _ArrayDisplay($selItems) ;BAD ConsoleWrite("Selected item: " & $selItems[1] & @CRLF) ; Array variable has incorrect number of subscripts or subscript dimension range exceeded.: EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_COMMAND Here's the output: Quote Array size: 1 Number of items: 0 Array: Link to comment Share on other sites More sharing options...
littlebigman Posted June 22, 2023 Author Share Posted June 22, 2023 (New reply since I can't figure out how to edit below the quote above). Fixed using this: ConsoleWrite(GUICtrlRead($hListBox) & @CRLF) Link to comment Share on other sites More sharing options...
Andreik Posted June 22, 2023 Share Posted June 22, 2023 (edited) Actually it's quite indicate to return from WM_COMMAND as fast as possible and you can do it through a simple Dummy control and do all the processing in your main loop or elsewhere. Here is an example: expandcollapse popup#include <Array.au3> Global $hMain, $cList1, $cList2, $cList3, $cDummy Global $hList1, $hList2, $hList3, $aMsg $hMain = GUICreate('Example', 900, 300) $cList1 = GUICtrlCreateList('', 0, 0, 300, 300) $cList2 = GUICtrlCreateList('', 300, 0, 300, 300) $cList3 = GUICtrlCreateList('', 600, 0, 300, 300) $cDummy = GUICtrlCreateDummy() $hList1 = GUICtrlGetHandle($cList1) $hList2 = GUICtrlGetHandle($cList2) $hList3 = GUICtrlGetHandle($cList3) GUISetState(@SW_SHOW, $hMain) GUIRegisterMsg(0x0111, 'WM_COMMAND') ; WM_COMMAND ; Add some lines in each list For $Index = 1 To 5 GUICtrlSetData($cList1, 'Line ' & $Index) GUICtrlSetData($cList2, 'Line ' & $Index) GUICtrlSetData($cList3, 'Line ' & $Index) Next While True Switch GUIGetMsg() Case -3 ; GUI_EVENT_CLOSE Exit Case $cDummy $aMsg = StringSplit(GUICtrlRead($cDummy), '|') Switch $aMsg[1] Case $cList1 Switch $aMsg[2] Case 1 ; LBN_SELCHANGE ConsoleWrite('Selection changed in first list.' & @CRLF) Case 2 ; LBN_DBLCLK ConsoleWrite('Double clicked in first list. (Item text: ' & GUICtrlRead($cList1) & ')' & @CRLF) EndSwitch Case $cList2 Switch $aMsg[2] Case 1 ; LBN_SELCHANGE ConsoleWrite('Selection changed in second list.' & @CRLF) Case 2 ; LBN_DBLCLK ConsoleWrite('Double clicked in second list. (Item text: ' & GUICtrlRead($cList2) & ')' & @CRLF) EndSwitch Case $cList3 Switch $aMsg[2] Case 1 ; LBN_SELCHANGE ConsoleWrite('Selection changed in third list.' & @CRLF) Case 2 ; LBN_DBLCLK ConsoleWrite('Double clicked in third list. (Item text: ' & GUICtrlRead($cList3) & ')' & @CRLF) EndSwitch EndSwitch EndSwitch Sleep(10) WEnd Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $iCtrlID = BitAND($wParam, 0xFFFF) ; Low Word Local $iNotificationCode = BitShift($wParam, 16) ; Hi Word Switch $lParam ; Control handle Case $hList1, $hList2, $hList3 GUICtrlSendToDummy($cDummy, $iCtrlID & '|' & $iNotificationCode) EndSwitch Return 'GUI_RUNDEFMSG' ; GUI_RUNDEFMSG EndFunc Edited June 22, 2023 by Andreik littlebigman 1 When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now