this-is-me Posted February 13, 2014 Share Posted February 13, 2014 I have a short and messy script that I am using to dynamically create a context menu of folders starting with C: My problem is that I would like to detect clicks on the menu item that opens a submenu, but these items do not return a message when clicked that I can see. My explanation is better understood in the following screenshot: When I click on a menu item that has a submenu, I would like something to happen in the script. I can probably figure it out from there. Please bear in mind that I would prefer to avoid _IsPressed and Mouse Hooks. Instead. I would like to make this object notify my script if possible. Here's the script as it is so far: expandcollapse popup#include <GuiMenu.au3> #include <GUIConstants.au3> #include <WindowsConstants.au3> #include <Constants.au3> #include <WinAPICom.au3> #include <WinAPIShellEx.au3> #include <GuiImageList.au3> #include <GDIPlus.au3> ;#include <..\..\ProjectIncludes\Debug.au3> ;$dbgType = $dbgTypeConsole Func dbg($str) ConsoleWrite($str & @CRLF) EndFunc Global $base = "C:" Global $lastMenuSelected = 0 Dim $dirs[1][2] _WinAPI_CoInitialize() _GDIPlus_Startup() GUIRegisterMsg($WM_INITMENUPOPUP, "WM_INITMENUPOPUP") ;GUIRegisterMsg($WM_UNINITMENUPOPUP, "WM_UNINITMENUPOPUP") GUIRegisterMsg($WM_MENUCOMMAND, "WM_MENUCOMMAND") GUIRegisterMsg($WM_MENUSELECT, "WM_MENUSELECT") Dim $hGUI = GUICreate("Test", 150, 150) Local $hIml = GetSystemImageList() $ctxmenu = GUICtrlGetHandle(GUICtrlCreateContextMenu()) $dirs[0][0] = $ctxmenu $dirs[0][1] = $base _GUICtrlMenu_SetMenuStyle($ctxmenu, $MNS_NOTIFYBYPOS) FillMenu($ctxmenu, $base) GUISetState() Do Until GUIGetMsg() = -3 GUIDelete() _WinAPI_CoUninitialize() _GDIPlus_Shutdown() Exit Func FindUpperDir($ID) Local $ub = UBound($dirs) For $i = 0 To $ub - 1 If $dirs[$i][0] = $ID Then Return $dirs[$i][1] Next EndFunc Func FillMenu($menu, $base) If $base = "" Then Return If _GUICtrlMenu_GetItemText($menu, 0) = "[Loading]" Then _GUICtrlMenu_DeleteMenu($menu, 0) $lst = ListFolders($base & "\") For $i = 1 To $lst[0] - 1 ;Last item in list of folders is always empty If $lst[$i] = "$Recycle.Bin" Or $lst[$i] = "winsxs" Then ContinueLoop Local $curFolder = $base & "\" & $lst[$i] Local $iImage = GetIconIndex($curFolder) If FolderHasAFolder($curFolder) Then ;Only make submenus out of folders with folders inside Local $newmenu = _GUICtrlMenu_CreatePopup() ;8+32 _GUICtrlMenu_AddMenuItem($newmenu, "[Loading]") _GUICtrlMenu_AppendMenu($menu, $MF_POPUP, $newmenu, $lst[$i]) Local $ub = UBound($dirs) ReDim $dirs[$ub + 1][2] $dirs[$ub][0] = $newmenu $dirs[$ub][1] = $curFolder Else _GUICtrlMenu_AddMenuItem($menu, $lst[$i]) EndIf Local $loc = _GUICtrlMenu_GetItemCount($menu) - 1 Local $hBitmap = hBitmapFromImageList($hIml, $iImage) _GUICtrlMenu_SetItemBmp($menu, $loc, $hBitmap) ;_WinAPI_DeleteObject($hBitmap) Next EndFunc Func hBitmapFromImageList($hImageList, $iIndex) Local $icon = _GUIImageList_GetIcon($hImageList, $iIndex) Local $bitmap = _GDIPlus_BitmapCreateFromHICON($icon) Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($bitmap) _GUIImageList_DestroyIcon($icon) _GDIPlus_ImageDispose($bitmap) Return $hBitmap EndFunc Func GetSystemImageList( $bLargeIcons = False ) Local $tSHFILEINFO = DllStructCreate( $tagSHFILEINFO ) Local $dwFlags = BitOR( $SHGFI_USEFILEATTRIBUTES, $SHGFI_SYSICONINDEX ) If Not $bLargeIcons Then $dwFlags = BitOR( $dwFlags, $SHGFI_SMALLICON ) Local $hIml = _WinAPI_ShellGetFileInfo( ".txt", $dwFlags, $FILE_ATTRIBUTE_NORMAL, $tSHFILEINFO ) If @error Then Return SetError( @error, 0, 0 ) Return $hIml EndFunc Func GetIconIndex( $sFileName ) Local $pPIDL = _WinAPI_ShellILCreateFromPath( $sFileName ) Local $tSHFILEINFO = DllStructCreate( $tagSHFILEINFO ) Local $iFlags = BitOr( $SHGFI_PIDL, $SHGFI_SYSICONINDEX ) ShellGetFileInfo( $pPIDL, $iFlags, 0, $tSHFILEINFO ) Local $iIcon = DllStructGetData( $tSHFILEINFO, "iIcon" ) _WinAPI_CoTaskMemFree( $pPIDL ) Return $iIcon EndFunc Func ShellGetFileInfo($pPIDL, $iFlags, $iAttributes, ByRef $tSHFILEINFO) Local $aRet = DllCall('shell32.dll', 'dword_ptr', 'SHGetFileInfoW', 'ptr', $pPIDL, 'dword', $iAttributes, 'struct*', $tSHFILEINFO, 'uint', DllStructGetSize($tSHFILEINFO), 'uint', $iFlags) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc Func FolderHasAFolder($dir) $search = FileFindFirstFile($dir & "\*") If Not @error Then While 1 $nxtfile = FileFindNextFile($search) If @error Then ExitLoop If StringInStr(FileGetAttrib($dir & "\" & $nxtfile), "D") Then FileClose($search) Return 1 EndIf WEnd EndIf FileClose($search) Return 0 EndFunc Func ListFolders($baseDir) Local $line = "" $foo = Run(@ComSpec & ' /c "dir /b /ad "' & $baseDir & '""', @SystemDir, @SW_HIDE, $STDOUT_CHILD) Do $line &= StdoutRead($foo) Until @error If StringInStr($line, "cannot find the file") Or StringInStr($line, "File Not Found") Then Return StringSplit("", "") Return StringSplit($line, @CRLF, 1) EndFunc Func WM_INITMENUPOPUP($hwnd, $iMsg, $iwParam, $ilParam) If _GUICtrlMenu_FindItem($iwParam, "[Loading]") <> -1 Then FillMenu($iwParam, FindUpperDir($iwParam)) Return $GUI_RUNDEFMSG EndFunc #cs Func WM_UNINITMENUPOPUP($hwnd, $iMsg, $iwParam, $ilParam) Switch $iwParam Case $ctxmenu ;_GUICtrlMenu_AddMenuItem($menu, "Test") ;_GUICtrlMenu_DestroyMenu($ctxmenu) EndSwitch Return "GUI_RUNDEFMSG" EndFunc #ce Func WM_MENUSELECT($hWnd, $iMsg, $iwParam, $ilParam) ;This performs the function of automatically scrolling long lists when the mouse is over the arrows. $lastMenuSelected = $ilParam If $iwParam = 0 And $iwParam = 0 Then MouseDown("primary") Return $GUI_RUNDEFMSG EndFunc Func WM_MENUCOMMAND($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg, $ilParam If _GUICtrlMenu_IsMenu($ilParam) Then $base = FindUpperDir($ilParam) $folder = _GUICtrlMenu_GetItemText($ilParam, $iwParam) dbg($base & "\" & $folder) EndIf Return $GUI_RUNDEFMSG EndFunc Simply run the script and right click to see a list of folders on your C: drive. Who else would I be? Link to comment Share on other sites More sharing options...
JohnOne Posted February 13, 2014 Share Posted February 13, 2014 What about capturing WM_LBUTTONUP and checking for the control ID? AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Danyfirex Posted February 13, 2014 Share Posted February 13, 2014 (edited) Hi. Change your WM_MENUSELECT for this: Edit. is not all that you want.but this part can help to know if is popup menu. Func WM_MENUSELECT($hWnd, $iMsg, $iwParam, $ilParam) Local $Flags = BitShift($iwParam, 16) If BitAND($Flags, $MF_POPUP) Then Consolewrite("I have An Arrow :)" & @crlf) EndIf Return $GUI_RUNDEFMSG EndFunc Saludos Edited February 13, 2014 by Danyfirex this-is-me 1 Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut Link to comment Share on other sites More sharing options...
this-is-me Posted February 14, 2014 Author Share Posted February 14, 2014 (edited) JohnOne, I am sorry to say that the WM_LBUTTONUP message is not generated from the menu. (EDIT: Actually even the form itself does not generate such a message, am I doing it wrong?) Danyfirex, Thanks for that little snippet of code. It has already helped help me. Anyone have another suggestion? Edited February 14, 2014 by this-is-me Who else would I be? Link to comment Share on other sites More sharing options...
JohnOne Posted February 14, 2014 Share Posted February 14, 2014 The message is generated, for me at least when I checked with spy++. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
this-is-me Posted February 14, 2014 Author Share Posted February 14, 2014 (edited) Sorry, I just tried with the gui, and the mouseup message is generated on the gui. My mistake, but the message is still not generated when on the menu, or is not sent to my program. Does it matter that this menu is not generated using built-in functions? I am using _GuiCtrlMenu_ functions to build the menu. Is that the difference? This is what I'm using to test it: GUIRegisterMsg($WM_LBUTTONUP, "WM_LBUTTONUP") Func WM_LBUTTONUP($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg, $ilParam ConsoleWrite("Mouse up" & @CRLF) Return $GUI_RUNDEFMSG EndFunc Edited February 14, 2014 by this-is-me Who else would I be? Link to comment Share on other sites More sharing options...
JohnOne Posted February 14, 2014 Share Posted February 14, 2014 I would have thought to get controlID with @GUI_CtrlId, but it errors out with unknown macro. Maybe it was removed. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted February 14, 2014 Moderators Share Posted February 14, 2014 JohnOne,The @GUI_CtrlID macro only exists inside a function called using OnEvent mode - as this script uses GUIGteMsg it hss no meaning, as you have discovered. M23 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
JohnOne Posted February 14, 2014 Share Posted February 14, 2014 (edited) Indeed, I looked in helpfile and read it, but still seen registermsg where it was setonevent. Selective seeing Edited February 14, 2014 by JohnOne AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
JohnOne Posted February 14, 2014 Share Posted February 14, 2014 So can the ID be obtained from $wparam or $lparam. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
JohnOne Posted February 14, 2014 Share Posted February 14, 2014 I believe the control ID might be got using code from an example by klomas >here. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
this-is-me Posted February 14, 2014 Author Share Posted February 14, 2014 I'm sorry to say that the only message I get from that code is a WM_ENTERIDLE message, which also happens every pixel the mouse moves. Who else would I be? Link to comment Share on other sites More sharing options...
JohnOne Posted February 14, 2014 Share Posted February 14, 2014 Sorry for wasting your time. It was the GUI receiving the messages not the control. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
this-is-me Posted February 14, 2014 Author Share Posted February 14, 2014 You didn't waste my time. Instead, I learned something. And, it seems that the only way to achieve my goal is to use a mouse hook, so that's what I'll do. Thanks for your help everyone. If anyone does come up with a solution other than a global mouse hook, I am willing to try it. Who else would I be? Link to comment Share on other sites More sharing options...
BrewManNH Posted February 14, 2014 Share Posted February 14, 2014 If you substitute this code with your WM_MENUSELECT function, you might be able to work with it. Func WM_MENUSELECT($hWnd, $iMsg, $iwParam, $ilParam) Local $index = _LoWord($iwParam) Local $flags = _HiWord($iwParam) _DebugPrint("index or identifier: " & $index) If BitAND($flags, $MF_BITMAP) Then _DebugPrint("$MF_BITMAP") If BitAND($flags, $MF_CHECKED) Then _DebugPrint("$MF_CHECKED") If BitAND($flags, $MF_DISABLED) Then _DebugPrint("$MF_DISABLED") If BitAND($flags, $MF_GRAYED) Then _DebugPrint("$MF_GRAYED") If BitAND($flags, $MF_HILITE) Then _DebugPrint("$MF_HILITE") If BitAND($flags, $MF_MOUSESELECT) Then _DebugPrint("$MF_MOUSESELECT") If BitAND($flags, $MF_OWNERDRAW) Then _DebugPrint("$MF_OWNERDRAW") If BitAND($flags, $MF_POPUP) Then _DebugPrint("$MF_POPUP") If BitAND($flags, $MF_SYSMENU) Then _DebugPrint("$MF_SYSMENU") If $ilParam Then _DebugPrint("Handle: " & $ilParam) Return $GUI_RUNDEFMSG EndFunc ; Helper functions. Func _HiWord($x) Return BitShift($x, 16) EndFunc ;==>_HiWord Func _LoWord($x) Return BitAND($x, 0xFFFF) EndFunc ;==>_LoWord Func _DebugPrint($s_text) $s_text = StringReplace(StringReplace($s_text, @CRLF, @LF), @LF, @LF & "!-->") ConsoleWrite( _ "+===========================================================" & @LF & _ "!-->" & $s_text & @LF & _ "+===========================================================" & @LF & @LF) EndFunc ;==>_DebugPrint this-is-me and mLipok 2 If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator Link to comment Share on other sites More sharing options...
this-is-me Posted February 15, 2014 Author Share Posted February 15, 2014 BrewManNH, thanks for the _LoWord value for the index. I needed that. Who else would I be? Link to comment Share on other sites More sharing options...
BrewManNH Posted February 15, 2014 Share Posted February 15, 2014 I inadvertently forgot to link where I got that snippet from, I didn't want any confusion created. '?do=embed' frameborder='0' data-embedContent>> If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator 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