Bilgus Posted March 26, 2018 Share Posted March 26, 2018 (edited) Example of Subclassing listviews using setwindowSubclass in order to intercept WM_KEYUP events Also pops context menu on Shift + F10 expandcollapse popup#include <Misc.au3> #include <ListViewConstants.au3> #include <GUIConstants.au3> #include <GuiMenu.au3> #include <WinAPIShellEx.au3> Global $g_hCB, $g_pCB, $g_ahProc[2][2] ;Stores the Data for subclassing listview Global $g_LVKEYUP = 0xFE00, $g_LVKEYDN = 0xFD00 ;Our Own Custom messages (Key Up/Dn) Global $g_iDummyData Global $g_hGui = GUICreate("test") Global $g_hList1 = GUICtrlCreateListView("#|x|y", 5, 24, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList1) Global $g_hList1_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callback Global $g_hContext1 = GUICtrlCreateContextMenu($g_hList1) GUICtrlCreateMenuItem("1", $g_hContext1) GUICtrlCreateMenuItem("2", $g_hContext1) Global $g_hList2 = GUICtrlCreateListView("#|x|y", 5, 100, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList2) Global $g_hList2_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callback Global $g_hContext2 = GUICtrlCreateContextMenu($g_hList2) GUICtrlCreateMenuItem("3", $g_hContext2) GUICtrlCreateMenuItem("4", $g_hContext2) GUISetState(@SW_SHOW) SubClassListView() ;Creates our subclass Func SubClassListView() OnAutoItExitRegister("Cleanup") ;to remove our subclass $g_hCB = DllCallbackRegister('_SubclassProc', 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr') $g_pCB = DllCallbackGetPtr($g_hCB) $g_ahProc[0][0] = $g_hList1 ;Add the Ids of the controls we'd like to subclass $g_ahProc[1][0] = $g_hList2 ;Set up the subclass _WinAPI_SetWindowSubclass ( $hWnd, $pSubclassProc, $idSubClass [, $pData = 0] ) $g_ahProc[0][1] = _WinAPI_SetWindowSubclass(GUICtrlGetHandle($g_ahProc[0][0]), $g_pCB, $g_ahProc[0][0], $g_hList1_LVN) $g_ahProc[1][1] = _WinAPI_SetWindowSubclass(GUICtrlGetHandle($g_ahProc[1][0]), $g_pCB, $g_ahProc[1][0], $g_hList2_LVN) EndFunc ;==>SubClassListView Func _SubclassProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) #forceref $iID Local $iRtnMsg = 0 ;Events we'd like to intercept If $iMsg = $WM_KEYUP Or $iMsg = $WM_SYSKEYUP Then $iRtnMsg = $g_LVKEYUP ElseIf $iMsg = $WM_KEYDOWN Or $iMsg = $WM_SYSKEYDOWN Then $iRtnMsg = $g_LVKEYDN EndIf ;We Recieve the Id of the dummy through $pData and pass our RtnMsg to the dummy control If $iRtnMsg Then GUICtrlSendToDummy($pData, BitOR($iRtnMsg, $wParam)) ;Pass messages on to the default handler Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_SubclassProc Func Cleanup() For $i = 0 To UBound($g_ahProc) - 1 ;Remove Our Subclass' by setting it back to the original proc _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($g_ahProc[$i][0]), DllCallbackGetPtr($g_ahProc[$i][1]), $g_ahProc[$i][0]) Next DllCallbackFree($g_hCB) EndFunc ;==>Cleanup While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $g_hList1_LVN ;This is just a dummy it only recieves events ConsoleWrite("LV1 EVENT 0x" & Hex($g_iDummyData, 4) & @CRLF) $g_iDummyData = GUICtrlRead($g_hList1_LVN) ;Retrieve the code that was sent Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN If BitAND($g_iDummyData, 0x00FF) = 0x79 And (_IsPressed("A0") Or _IsPressed("A1")) Then ;Right/ Left Shift & F10 ShowMenu($g_hGui, $g_hList1, $g_hContext1) Else ConsoleWrite("Lv1 KeyDn Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndIf Case $g_LVKEYUP ConsoleWrite("Lv1 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch Case $g_hList2_LVN $g_iDummyData = GUICtrlRead($g_hList2_LVN) ;Retrieve the code that was sent ConsoleWrite("LV2 EVENT 0x" & Hex($g_iDummyData, 4) & @CRLF) Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN ConsoleWrite("Lv2 KeyDn Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode Case $g_LVKEYUP ConsoleWrite("Lv2 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch EndSwitch WEnd Func ShowMenu($hWnd, $idCtrl, $idContext) Local $aPos, $iX, $iY Local $hMenu = GUICtrlGetHandle($idContext) $aPos = ControlGetPos($hWnd, "", $idCtrl) $iX = $aPos[0] $iY = $aPos[1] + $aPos[3] ClientToScreen($hWnd, $iX, $iY) ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd, $iX, $iY) EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hWnd, ByRef $iX, ByRef $iY) Local $tPoint = DllStructCreate("int;int") DllStructSetData($tPoint, 1, $iX) DllStructSetData($tPoint, 2, $iY) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPoint) $iX = DllStructGetData($tPoint, 1) $iY = DllStructGetData($tPoint, 2) ; release Struct not really needed as it is a local $tPoint = 0 EndFunc ;==>ClientToScreen Old Code Using setWindowLong Spoiler expandcollapse popup#include <Misc.au3> #include <ListViewConstants.au3> #include <GUIConstants.au3> #include <GuiMenu.au3> #include <WinAPISys.au3> Global $g_hCB, $g_pCB, $g_hProc[2][2] ;Stores the Data for subclassing listview Global $g_LVKEYUP = 0xFE00, $g_LVKEYDN = 0xFD00 ;Our Own Custom Key Up/Dn messages Global $g_iDummyData Global $g_hGui = GUICreate("test") Global $g_hList1 = GUICtrlCreateListView("#|x|y", 5, 24, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList1) Global $g_hList1_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callbacks Global $g_hContext1 = GUICtrlCreateContextMenu($g_hList1) GUICtrlCreateMenuItem("1", $g_hContext1) GUICtrlCreateMenuItem("2", $g_hContext1) Global $g_hList2 = GUICtrlCreateListView("#|x|y", 5, 100, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList2) Global $g_hList2_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callbacks Global $g_hContext2 = GUICtrlCreateContextMenu($g_hList2) GUICtrlCreateMenuItem("3", $g_hContext2) GUICtrlCreateMenuItem("4", $g_hContext2) GUISetState() SubClassListView() ;Creates our subclass Func SubClassListView() OnAutoItExitRegister("Cleanup") ;to remove our subclass Local $iPID $g_hCB = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam') $g_pCB = DllCallbackGetPtr($g_hCB) $g_hProc[0][0] = GUICtrlGetHandle($g_hList1) $g_hProc[1][0] = GUICtrlGetHandle($g_hList2) $g_hProc[0][1] = _WinAPI_SetWindowLong($g_hProc[0][0], $GWL_WNDPROC, $g_pCB) $g_hProc[1][1] = _WinAPI_SetWindowLong($g_hProc[1][0], $GWL_WNDPROC, $g_pCB) EndFunc ;==>SubClassWndProc Func _WinProc($hWnd, $iMsg, $wParam, $lParam) Local $iRtnMsg = 0 If $iMsg = $WM_KEYUP Or $iMsg = $WM_SYSKEYUP Then $iRtnMsg = $g_LVKEYUP ElseIf $iMsg = $WM_KEYDOWN Or $iMsg = $WM_SYSKEYDOWN Then $iRtnMsg = $g_LVKEYDN EndIf Switch $hWnd Case $g_hProc[0][0] If $iRtnMsg Then GUICtrlSendToDummy($g_hList1_LVN, BitOR($iRtnMsg, $wParam)) Return _WinAPI_CallWindowProc($g_hProc[0][1], $hWnd, $iMsg, $wParam, $lParam) Case $g_hProc[1][0] If $iRtnMsg Then GUICtrlSendToDummy($g_hList2_LVN, BitOR($iRtnMsg, $wParam)) Return _WinAPI_CallWindowProc($g_hProc[1][1], $hWnd, $iMsg, $wParam, $lParam) EndSwitch EndFunc ;==>_WinProc Func Cleanup() _WinAPI_SetWindowLong($g_hProc[0][0], $GWL_WNDPROC, $g_hProc[0][1]);Remove our subclass _WinAPI_SetWindowLong($g_hProc[1][0], $GWL_WNDPROC, $g_hProc[1][1]);Remove our subclass DllCallbackFree($g_hCB) EndFunc ;==>Cleanup While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $g_hList1_LVN ;This is just a dummy it only recieves events ConsoleWrite("LV1 EVENT 0x" & Hex(BitAND($g_iDummyData, 0xFF00), 4) & @CRLF) $g_iDummyData = GUICtrlRead($g_hList1_LVN) ;Retrieve the code that was sent Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN If BitAND($g_iDummyData, 0x00FF) = 0x79 And (_IsPressed("A0") Or _IsPressed("A1")) Then ;Right/ Left Shift & F10 ShowMenu($g_hGui, $g_hList1, $g_hContext1) Else ConsoleWrite("Lv1 KeyDN Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndIf Case $g_LVKEYUP ConsoleWrite("Lv1 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch Case $g_hList2_LVN $g_iDummyData = GUICtrlRead($g_hList2_LVN) ;Retrieve the code that was sent ConsoleWrite("LV2 EVENT 0x" & Hex(BitAND($g_iDummyData, 0xFF00), 4) & @CRLF) Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN ConsoleWrite("Lv2 KeyDN Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode Case $g_LVKEYUP ConsoleWrite("Lv2 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch EndSwitch WEnd Func ShowMenu($hWnd, $idCtrl, $idContext) Local $aPos, $iX, $iY Local $hMenu = GUICtrlGetHandle($idContext) $aPos = ControlGetPos($hWnd, "", $idCtrl) $iX = $aPos[0] $iY = $aPos[1] + $aPos[3] ClientToScreen($hWnd, $iX, $iY) ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd, $iX, $iY) EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hWnd, ByRef $iX, ByRef $iY) Local $tPoint = DllStructCreate("int;int") DllStructSetData($tPoint, 1, $iX) DllStructSetData($tPoint, 2, $iY) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPoint) $iX = DllStructGetData($tPoint, 1) $iY = DllStructGetData($tPoint, 2) ; release Struct not really needed as it is a local $tPoint = 0 EndFunc ;==>ClientToScreen Edited March 26, 2018 by Bilgus Link to comment Share on other sites More sharing options...
kklee69 Posted March 26, 2018 Share Posted March 26, 2018 9 hours ago, Bilgus said: Example of Subclassing listviews using setwindowlong in order to intercept WM_KEYUP events Also pops context menu on Shift + F10 expandcollapse popup#include <Misc.au3> #include <ListViewConstants.au3> #include <GUIConstants.au3> #include <GuiMenu.au3> #include <WinAPISys.au3> Global $g_hCB, $g_pCB, $g_hProc[2][2] ;Stores the Data for subclassing listview Global $g_LVKEYUP = 0xFE00, $g_LVKEYDN = 0xFD00 ;Our Own Custom Key Up/Dn messages Global $g_iDummyData Global $g_hGui = GUICreate("test") Global $g_hList1 = GUICtrlCreateListView("#|x|y", 5, 24, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList1) Global $g_hList1_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callbacks Global $g_hContext1 = GUICtrlCreateContextMenu($g_hList1) GUICtrlCreateMenuItem("1", $g_hContext1) GUICtrlCreateMenuItem("2", $g_hContext1) Global $g_hList2 = GUICtrlCreateListView("#|x|y", 5, 100, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList2) Global $g_hList2_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callbacks Global $g_hContext2 = GUICtrlCreateContextMenu($g_hList2) GUICtrlCreateMenuItem("3", $g_hContext2) GUICtrlCreateMenuItem("4", $g_hContext2) GUISetState() SubClassListView() ;Creates our subclass Func SubClassListView() OnAutoItExitRegister("Cleanup") ;to remove our subclass Local $iPID $g_hCB = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam') $g_pCB = DllCallbackGetPtr($g_hCB) $g_hProc[0][0] = GUICtrlGetHandle($g_hList1) $g_hProc[1][0] = GUICtrlGetHandle($g_hList2) $g_hProc[0][1] = _WinAPI_SetWindowLong($g_hProc[0][0], $GWL_WNDPROC, $g_pCB) $g_hProc[1][1] = _WinAPI_SetWindowLong($g_hProc[1][0], $GWL_WNDPROC, $g_pCB) EndFunc ;==>SubClassWndProc Func _WinProc($hWnd, $iMsg, $wParam, $lParam) Local $iRtnMsg = 0 If $iMsg = $WM_KEYUP Or $iMsg = $WM_SYSKEYUP Then $iRtnMsg = $g_LVKEYUP ElseIf $iMsg = $WM_KEYDOWN Or $iMsg = $WM_SYSKEYDOWN Then $iRtnMsg = $g_LVKEYDN EndIf Switch $hWnd Case $g_hProc[0][0] If $iRtnMsg Then GUICtrlSendToDummy($g_hList1_LVN, BitOR($iRtnMsg, $wParam)) Return _WinAPI_CallWindowProc($g_hProc[0][1], $hWnd, $iMsg, $wParam, $lParam) Case $g_hProc[1][0] If $iRtnMsg Then GUICtrlSendToDummy($g_hList2_LVN, BitOR($iRtnMsg, $wParam)) Return _WinAPI_CallWindowProc($g_hProc[1][1], $hWnd, $iMsg, $wParam, $lParam) EndSwitch EndFunc ;==>_WinProc Func Cleanup() _WinAPI_SetWindowLong($g_hProc[0][0], $GWL_WNDPROC, $g_hProc[0][1]);Remove our subclass _WinAPI_SetWindowLong($g_hProc[1][0], $GWL_WNDPROC, $g_hProc[1][1]);Remove our subclass DllCallbackFree($g_hCB) EndFunc ;==>Cleanup While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $g_hList1_LVN ;This is just a dummy it only recieves events ConsoleWrite("LV1 EVENT 0x" & Hex(BitAND($g_iDummyData, 0xFF00), 4) & @CRLF) $g_iDummyData = GUICtrlRead($g_hList1_LVN) ;Retrieve the code that was sent Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN If BitAND($g_iDummyData, 0x00FF) = 0x79 And (_IsPressed("A0") Or _IsPressed("A1")) Then ;Right/ Left Shift & F10 ShowMenu($g_hGui, $g_hList1, $g_hContext1) Else ConsoleWrite("Lv1 KeyDN Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndIf Case $g_LVKEYUP ConsoleWrite("Lv1 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch Case $g_hList2_LVN $g_iDummyData = GUICtrlRead($g_hList2_LVN) ;Retrieve the code that was sent ConsoleWrite("LV2 EVENT 0x" & Hex(BitAND($g_iDummyData, 0xFF00), 4) & @CRLF) Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN ConsoleWrite("Lv2 KeyDN Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode Case $g_LVKEYUP ConsoleWrite("Lv2 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch EndSwitch WEnd Func ShowMenu($hWnd, $idCtrl, $idContext) Local $aPos, $iX, $iY Local $hMenu = GUICtrlGetHandle($idContext) $aPos = ControlGetPos($hWnd, "", $idCtrl) $iX = $aPos[0] $iY = $aPos[1] + $aPos[3] ClientToScreen($hWnd, $iX, $iY) ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd, $iX, $iY) EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hWnd, ByRef $iX, ByRef $iY) Local $tPoint = DllStructCreate("int;int") DllStructSetData($tPoint, 1, $iX) DllStructSetData($tPoint, 2, $iY) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPoint) $iX = DllStructGetData($tPoint, 1) $iY = DllStructGetData($tPoint, 2) ; release Struct not really needed as it is a local $tPoint = 0 EndFunc ;==>ClientToScreen This is very cool code !!Help me a lot I need some time to study Thank you again Link to comment Share on other sites More sharing options...
Bilgus Posted March 26, 2018 Author Share Posted March 26, 2018 Updated Code to using SetWindowSubclass() instead of setwindowlong This allows us to pass the ID of the dummy control through the pData Variable which cleans up the subclass procedure a bit Link to comment Share on other sites More sharing options...
spudw2k Posted March 29, 2018 Share Posted March 29, 2018 Neat approach. I was looking for a way to implement looking for the $WM_CONTEXTMENU notification instead of listening specifically for the Right-Click or Shift+F10 inputs. That way they (along with the application/menu key) would work without special checks. My quick implementation was producing two menu pop-ups though and I'm not sure why. Spoiler Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retrieve SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc Cool Stuff: AutoItObject UDF ◊ Extract Icon From Proc ◊ GuiCtrlFontRotate ◊ Hex Edit Funcs ◊ Run binary ◊ Service_UDF Link to comment Share on other sites More sharing options...
Bilgus Posted March 29, 2018 Author Share Posted March 29, 2018 (edited) @spudw2k If you are just wanting some control over the context menu this example is probably a bit much since its meant to get KeyUp events before the listview has a chance to eat the message Instead THIS might be a bit better expandcollapse popup#include <Misc.au3> #include <ListViewConstants.au3> #include <GUIConstants.au3> #include <GuiMenu.au3> Global $GUI = GUICreate("test") Global $g_iTemp Global $g_hList1 = GUICtrlCreateListView("#|x|y", 5, 24, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList1) Global $g_hList1_LVN = GUICtrlCreateDummy() Global $context = GUICtrlCreateContextMenu($g_hList1_LVN);Just Associating with dummy so we can have multiple menu GUICtrlCreateMenuItem("1", $context) GUICtrlCreateMenuItem("2", $context) Global $contextH = GUICtrlCreateContextMenu($g_hList1);Only for header since we intercept rightclick on items GUICtrlCreateMenuItem("1Header", $contextH) GUICtrlCreateMenuItem("2Header", $contextH) Global $g_hList2 = GUICtrlCreateListView("#|x|y", 5, 100, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList2) Global $g_hList2_LVN = GUICtrlCreateDummy() Global $context2 = GUICtrlCreateContextMenu($g_hList2_LVN) ;Just Associating with dummy so we can have multiple menus GUICtrlCreateMenuItem("3", $context2) GUICtrlCreateMenuItem("4", $context2) Global $context2H = GUICtrlCreateContextMenu($g_hList2) ;Nothing Here GUISetState() GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") While 1 Switch GUIGetMsg() Case $gui_event_close Exit Case $g_hList1_LVN ;This is just a dummy it only recieves events ConsoleWrite("LV1 EVENT" & @CRLF) $g_iTemp = GUICtrlRead($g_hList1_LVN) ;Retrieve the code that WM_NOTIFY SENT If $g_iTemp = $LVN_KEYDOWN Then If _IsPressed("79") And (_IsPressed("A0") Or _IsPressed("A1")) Then ;Right/ Left Shift & F10 ShowMenu($GUI, $g_hList1, $context) Else ConsoleWrite("Some Other Keys" & @CRLF) EndIf ElseIf $g_iTemp = $NM_RCLICK Then ShowMenu($GUI, $g_hList1, $context) Else ConsoleWrite("Some Other Event Lv1" & @CRLF) EndIf Case $g_hList2_LVN ConsoleWrite("LV2 EVENT" & @CRLF) $g_iTemp = GUICtrlRead($g_hList2_LVN) If $g_iTemp = $LVN_KEYDOWN Then If _IsPressed("79") And (_IsPressed("A0") Or _IsPressed("A1")) Then ;Right/ Left Shift & F10 ShowMenu($GUI, $g_hList2, $context2) EndIf ElseIf $g_iTemp = $NM_RCLICK Then ShowMenu($GUI, $g_hList2, $context2) Else ConsoleWrite("Some Other Event Lv2" & @CRLF) EndIf EndSwitch WEnd Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tNMHDR, $iCode ; Switch $wParam Case $g_hList1 $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $iCode = DllStructGetData($tNMHDR, "Code") Switch $iCode Case $LVN_KEYDOWN, $NM_CLICK GUICtrlSendToDummy($g_hList1_LVN, $iCode) ;send the code back to be processed by the dummy Case $NM_RCLICK GUICtrlSendToDummy($g_hList1_LVN, $iCode) Return 1 ;Don't pass message onto default handler EndSwitch Case $g_hList2 $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $iCode = DllStructGetData($tNMHDR, "Code") Switch $iCode Case $LVN_KEYDOWN, $NM_CLICK GUICtrlSendToDummy($g_hList2_LVN, $iCode) Case $NM_RCLICK GUICtrlSendToDummy($g_hList2_LVN, $iCode) Return 1 ;Don't pass message onto default handler EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Func ShowMenu($hWnd, $idCtrl, $idContext) ConsoleWrite("POPUP MENU") Local $aPos, $x, $y Local $hMenu = GUICtrlGetHandle($idContext) $aPos = ControlGetPos($hWnd, "", $idCtrl) $x = $aPos[0] $y = $aPos[1] + $aPos[3] ClientToScreen($hWnd, $x, $y) TrackPopupMenu($hWnd, $hMenu, $x, $y) EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hWnd, ByRef $x, ByRef $y) Local $tPoint = DllStructCreate("int;int") DllStructSetData($tPoint, 1, $x) DllStructSetData($tPoint, 2, $y) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPoint) $x = DllStructGetData($tPoint, 1) $y = DllStructGetData($tPoint, 2) ; release Struct not really needed as it is a local $tPoint = 0 EndFunc ;==>ClientToScreen ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) Func TrackPopupMenu($hWnd, $hMenu, $x, $y) _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd, $x, $y) EndFunc ;==>TrackPopupMenu Edit I tried with WM_ContextMenu and while it does recieve Shift+F10 it lags behind on notifications and isn't able to be blocked either so I'd say thats probably the reason for the behavior you saw.. My guess is that the listview implements its own context popup Spoiler expandcollapse popup#include <Misc.au3> #include <ListViewConstants.au3> #include <GUIConstants.au3> #include <GuiMenu.au3> Global $GUI = GUICreate("test") Global $g_IdList1 = GUICtrlCreateListView("#|x|y", 5, 24, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) Global $g_hList1 = GUICtrlGetHandle ($g_IdList1) GUICtrlCreateListViewItem("text", $g_IdList1) Global $context = GUICtrlCreateContextMenu($g_IdList1) GUICtrlCreateMenuItem("1", $context) GUICtrlCreateMenuItem("2", $context) Global $g_IdList2 = GUICtrlCreateListView("#|x|y", 5, 100, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) Global $g_hList2 = GUICtrlGetHandle ($g_IdList2) GUICtrlCreateListViewItem("text", $g_IdList2) Global $context2 = GUICtrlCreateContextMenu($g_IdList2) GUICtrlCreateMenuItem("3", $context2) GUICtrlCreateMenuItem("4", $context2) GUISetState(@SW_SHOW) GUIRegisterMsg($WM_CONTEXTMENU, WM_CONTEXTMENU) GUIRegisterMsg($WM_ENTERMENULOOP, WM_CONTEXTMENU) While 1 Switch GUIGetMsg() Case $gui_event_close Exit EndSwitch WEnd Func WM_CONTEXTMENU($hWnd, $iMsg, $wParam, $lParam) Switch $wParam Case $g_hList1 ConsoleWrite("LV1 " & Hex($hWnd) & @CRLF) Case $g_hList2 ConsoleWrite("LV2 " & Hex($hWnd) & @CRLF) Case Else If $iMsg = $WM_ENTERMENULOOP Then ConsoleWrite("ENTERMENULOOP: " & Hex($hWnd) & " TrackPopup: " & ($wParam ? "True":"False") & @CRLF) EndIf EndSwitch Return $GUI_RUNDEFMSG EndFunc Func ShowMenu($hWnd, $idCtrl, $idContext) ConsoleWrite("POPUP MENU") Local $aPos, $x, $y Local $hMenu = GUICtrlGetHandle($idContext) $aPos = ControlGetPos($hWnd, "", $idCtrl) $x = $aPos[0] $y = $aPos[1] + $aPos[3] ClientToScreen($hWnd, $x, $y) TrackPopupMenu($hWnd, $hMenu, $x, $y) EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hWnd, ByRef $x, ByRef $y) Local $tPoint = DllStructCreate("int;int") DllStructSetData($tPoint, 1, $x) DllStructSetData($tPoint, 2, $y) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPoint) $x = DllStructGetData($tPoint, 1) $y = DllStructGetData($tPoint, 2) ; release Struct not really needed as it is a local $tPoint = 0 EndFunc ;==>ClientToScreen ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) Func TrackPopupMenu($hWnd, $hMenu, $x, $y) _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd, $x, $y) EndFunc ;==>TrackPopupMenu Edited March 29, 2018 by Bilgus 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