FunkyBunnies Posted April 12, 2009 Posted April 12, 2009 (edited) Hi all, I'm working on a toolbar that has a user-customizable number of buttons that each need to have their own context menu so I got help from people here and this is what I've come up with. It works totally fine except when a normal context menu pops up over a button that has a context menu it'll pop up the button's context menu when you click the menuitem. It seems to be registering a right click over the menuitem that i select - which triggers the custom context menu... any help would be outstanding is there way to query whether or not a context menu is popped up? could I disable the custom context menu? I'm at a loss try this test code and you'll see what I mean. Try right clicking on the title label and click on a menuitem that pops up ontop of a button Test: expandcollapse popup#include <GUIConstantsEx.au3> #include <ButtonConstants.au3> #include <WindowsConstants.au3> Opt("GUIResizeMode", $GUI_DOCKALL) ;try and change buttons to activate on buttonUP so that dragging and releasing ontop of a button will work ;what about using static ctrls for buttons?...regular buttons are a lot simpler Global $Buttonid[4] $Buttonid[0] = 3;num buttons _Main() Func _Main() Local $ExitID, $GUIMenu, $GUIMenu_About, $GUIMenu_Exit Local $ButtonMenu, $ButtonMenu_Dummy, $ButtonMenu_Test1, $ButtonMenu_Test2 ;create main ui $hGUI = GUICreate("Test GUI", 160, 80, -1, -1, $WS_POPUP + $WS_SIZEBOX, $GUI_WS_EX_PARENTDRAG) $GUIMenu = GUICtrlCreateContextMenu(-1) $GUIMenu_About = GUICtrlCreateMenuItem("About", $GUIMenu) $GUIMenu_Exit = GUICtrlCreateMenuItem("Exit", $GUIMenu) $toolbarTitle = GUICtrlCreateLabel("Test GUI", 5, 5, 180, 20, -1, $GUI_WS_EX_PARENTDRAG) $GUIMenuTB = GUICtrlCreateContextMenu($toolbarTitle) $GUIMenuTB_About = GUICtrlCreateMenuItem("About", $GUIMenuTB) $GUIMenuTB_Exit = GUICtrlCreateMenuItem("Exit", $GUIMenuTB) ;three buttons... $Buttonid[1] = GUICtrlCreateButton( "Test1", 10, 20, 40, 40) $Buttonid[2] = GUICtrlCreateButton( "Test2", 60, 20, 40, 40) $Buttonid[3] = GUICtrlCreateButton( "Test3", 110, 20, 40, 40) GUICtrlSetResizing ( $toolbarTitle, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKHEIGHT ) ;dummy to store index of button $ButtonMenu_Dummy = GUICtrlCreateDummy() $ButtonMenu = GUICtrlCreateContextMenu($ButtonMenu_Dummy) $ButtonMenu_Test1 = GUICtrlCreateMenuItem("ButtonMenu test1", $ButtonMenu) $ButtonMenu_Test2 = GUICtrlCreateMenuItem("ButtonMenu test2", $ButtonMenu) GUISetState(@SW_SHOW) While 1 ;start the message loop!!!! $msg = GUIGetMsg() local $i=1 While UBound($Buttonid) > $i If $msg == $Buttonid[$i] Then MsgBox(0, "button pressed", "You've pressed button #" & $i, 2) ExitLoop EndIf $i += 1 WEnd If $msg == $GUI_EVENT_CLOSE Or $msg == $GUIMenu_Exit Or $msg == $GUIMenuTB_Exit Or $msg == $ExitID Then GUIDelete($hGUI) Exit ElseIf $msg == $GUIMenu_About Or $msg == $GUIMenuTB_About Then Msgbox(64, "About", "blah blah blah") ElseIf $msg == $ButtonMenu_Test1 Then $index = GUICtrlRead($ButtonMenu_Dummy) MsgBox(0, "Context menu pressed", "test1 pressed from button #" &$index, 2) ElseIf $msg == $ButtonMenu_Test2 Then $index = GUICtrlRead($ButtonMenu_Dummy) MsgBox(0, "Context menu pressed", "test2 pressed from button #" &$index, 2) ElseIf $msg == $GUI_EVENT_SECONDARYUP Then ShowMenu($hGUI, $ButtonMenu, $ButtonMenu_Dummy, $ButtonMenu_Test1, $ButtonMenu_Test2) EndIf WEnd EndFunc ;==>_Main ;---------------Button Ctx menu functions--------------- Func ShowMenu($hGUI, $ButtonMenu, $ButtonMenu_Dummy, $ButtonMenu_Test1, $ButtonMenu_Test2) $hover = GUIGetCursorInfo($hGUI);get what control the mouse is over at this point and relative position for popup placement $hitX = $hover[0] $hitY = $hover[1] For $i=1 to (UBound($Buttonid)-1) If $hover[4] == $Buttonid[$i] And $hover[2] == 0 Then GUICtrlSendToDummy ($ButtonMenu_Dummy, $i); send index of hit item to dummy for reading later ;set new text GUICtrlSetData($ButtonMenu_Test1, "ButtonMenu #" & $i & " test1") GUICtrlSetData($ButtonMenu_Test2, "ButtonMenu #" & $i & " test2") Local $hMenu = GUICtrlGetHandle($ButtonMenu) ClientToScreen($hGUI, $hitX, $hitY) TrackPopupMenu($hGUI, $hMenu, $hitX, $hitY) Return EndIf Next EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hGUI, ByRef $x, ByRef $y) Local $stPoint = DllStructCreate("int;int") DllStructSetData($stPoint, 1, $x) DllStructSetData($stPoint, 2, $y) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hGUI, "ptr", DllStructGetPtr($stPoint)) $x = DllStructGetData($stPoint, 1) $y = DllStructGetData($stPoint, 2) ; release Struct not really needed as it is a local $stPoint = 0 EndFunc ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) Func TrackPopupMenu($hGUI, $hMenu, $x, $y) DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hGUI, "ptr", 0) EndFunc Edited April 12, 2009 by FunkyBunnies
martin Posted April 12, 2009 Posted April 12, 2009 FunkyBunnies said: Hi all, I'm working on a toolbar that has a user-customizable number of buttons that each need to have their own context menu so I got help from people here and this is what I've come up with. It works totally fine except when a normal context menu pops up over a button that has a context menu it'll pop up the button's context menu when you click the menuitem. It seems to be registering a right click over the menuitem that i select - which triggers the custom context menu... any help would be outstanding is there way to query whether or not a context menu is popped up? could I disable the custom context menu? I'm at a loss try this test code and you'll see what I mean. Try right clicking on the title label and click on a menuitem that pops up ontop of a button Test: expandcollapse popup#include <GUIConstantsEx.au3> #include <ButtonConstants.au3> #include <WindowsConstants.au3> Opt("GUIResizeMode", $GUI_DOCKALL) ;try and change buttons to activate on buttonUP so that dragging and releasing ontop of a button will work ;what about using static ctrls for buttons?...regular buttons are a lot simpler Global $Buttonid[4] $Buttonid[0] = 3;num buttons _Main() Func _Main() Local $ExitID, $GUIMenu, $GUIMenu_About, $GUIMenu_Exit Local $ButtonMenu, $ButtonMenu_Dummy, $ButtonMenu_Test1, $ButtonMenu_Test2 ;create main ui $hGUI = GUICreate("Test GUI", 160, 80, -1, -1, $WS_POPUP + $WS_SIZEBOX, $GUI_WS_EX_PARENTDRAG) $GUIMenu = GUICtrlCreateContextMenu(-1) $GUIMenu_About = GUICtrlCreateMenuItem("About", $GUIMenu) $GUIMenu_Exit = GUICtrlCreateMenuItem("Exit", $GUIMenu) $toolbarTitle = GUICtrlCreateLabel("Test GUI", 5, 5, 180, 20, -1, $GUI_WS_EX_PARENTDRAG) $GUIMenuTB = GUICtrlCreateContextMenu($toolbarTitle) $GUIMenuTB_About = GUICtrlCreateMenuItem("About", $GUIMenuTB) $GUIMenuTB_Exit = GUICtrlCreateMenuItem("Exit", $GUIMenuTB) ;three buttons... $Buttonid[1] = GUICtrlCreateButton( "Test1", 10, 20, 40, 40) $Buttonid[2] = GUICtrlCreateButton( "Test2", 60, 20, 40, 40) $Buttonid[3] = GUICtrlCreateButton( "Test3", 110, 20, 40, 40) GUICtrlSetResizing ( $toolbarTitle, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKHEIGHT ) ;dummy to store index of button $ButtonMenu_Dummy = GUICtrlCreateDummy() $ButtonMenu = GUICtrlCreateContextMenu($ButtonMenu_Dummy) $ButtonMenu_Test1 = GUICtrlCreateMenuItem("ButtonMenu test1", $ButtonMenu) $ButtonMenu_Test2 = GUICtrlCreateMenuItem("ButtonMenu test2", $ButtonMenu) GUISetState(@SW_SHOW) While 1 ;start the message loop!!!! $msg = GUIGetMsg() local $i=1 While UBound($Buttonid) > $i If $msg == $Buttonid[$i] Then MsgBox(0, "button pressed", "You've pressed button #" & $i, 2) ExitLoop EndIf $i += 1 WEnd If $msg == $GUI_EVENT_CLOSE Or $msg == $GUIMenu_Exit Or $msg == $GUIMenuTB_Exit Or $msg == $ExitID Then GUIDelete($hGUI) Exit ElseIf $msg == $GUIMenu_About Or $msg == $GUIMenuTB_About Then Msgbox(64, "About", "blah blah blah") ElseIf $msg == $ButtonMenu_Test1 Then $index = GUICtrlRead($ButtonMenu_Dummy) MsgBox(0, "Context menu pressed", "test1 pressed from button #" &$index, 2) ElseIf $msg == $ButtonMenu_Test2 Then $index = GUICtrlRead($ButtonMenu_Dummy) MsgBox(0, "Context menu pressed", "test2 pressed from button #" &$index, 2) ElseIf $msg == $GUI_EVENT_SECONDARYUP Then ShowMenu($hGUI, $ButtonMenu, $ButtonMenu_Dummy, $ButtonMenu_Test1, $ButtonMenu_Test2) EndIf WEnd EndFunc ;==>_Main ;---------------Button Ctx menu functions--------------- Func ShowMenu($hGUI, $ButtonMenu, $ButtonMenu_Dummy, $ButtonMenu_Test1, $ButtonMenu_Test2) $hover = GUIGetCursorInfo($hGUI);get what control the mouse is over at this point and relative position for popup placement $hitX = $hover[0] $hitY = $hover[1] For $i=1 to (UBound($Buttonid)-1) If $hover[4] == $Buttonid[$i] And $hover[2] == 0 Then GUICtrlSendToDummy ($ButtonMenu_Dummy, $i); send index of hit item to dummy for reading later ;set new text GUICtrlSetData($ButtonMenu_Test1, "ButtonMenu #" & $i & " test1") GUICtrlSetData($ButtonMenu_Test2, "ButtonMenu #" & $i & " test2") Local $hMenu = GUICtrlGetHandle($ButtonMenu) ClientToScreen($hGUI, $hitX, $hitY) TrackPopupMenu($hGUI, $hMenu, $hitX, $hitY) Return EndIf Next EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hGUI, ByRef $x, ByRef $y) Local $stPoint = DllStructCreate("int;int") DllStructSetData($stPoint, 1, $x) DllStructSetData($stPoint, 2, $y) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hGUI, "ptr", DllStructGetPtr($stPoint)) $x = DllStructGetData($stPoint, 1) $y = DllStructGetData($stPoint, 2) ; release Struct not really needed as it is a local $stPoint = 0 EndFunc ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) Func TrackPopupMenu($hGUI, $hMenu, $x, $y) DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hGUI, "ptr", 0) EndFuncWhen the secondary mouse button is pressed and the mouse is not over a button the context menu for the gui is shown. Then the secondary button is released but this event is queued until the gui context menu is closed which happens when you left click. I think that's what happens at least. So if you use $GUI_EVENT_SECONDARYDOWN instead of $GUI_EVENT_SECONDARYUP it might work. Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Authenticity Posted April 12, 2009 Posted April 12, 2009 You're making it more troubles attraction than it is: expandcollapse popup#include <GuiConstants.au3> Dim $hGUI = GUICreate('Test', 240, 140) Dim $GUIMenu = GUICtrlCreateContextMenu() Dim $About_Menu = GUICtrlCreateMenuItem('About', $GUIMenu) Dim $Exit_Menu = GUICtrlCreateMenuItem('Exit', $GUIMenu) Dim $Buttons[4] = [3], $Menus[4][3] = [[3,2,0]] For $i = 1 To $Buttons[0] $Buttons[$i] = GUICtrlCreateButton('#' & $i, 20+($i-1)*70, 40, 50, 50) Local $Button_Menu = GUICtrlCreateContextMenu($Buttons[$i]) For $j = 0 To $Menus[0][1] $Menus[$i][$j] = GUICtrlCreateMenuItem('B' & $i & '->#' & $j+1, $Button_Menu) Next Next GUISetState() While 1 Local $Msg = GUIGetMsg() Switch $Msg Case $About_Menu MsgBox(0x40, 'Title', '(\/)' & @LF & '(oO)' & @LF & '(")(")') Case $Exit_Menu, $GUI_EVENT_CLOSE ExitLoop Case Else _WhoCalls($Msg, $Buttons, $Menus) EndSwitch Sleep(20) WEnd GUIDelete() Func _WhoCalls($iIDFrom, ByRef $Btns, ByRef $Mns) For $i = 1 To $Btns[0] If $iIDFrom = $Btns[$i] Then MsgBox(0x40, 'Button Message!', 'From button: #' & $i) ExitLoop EndIf For $j = 0 To $Mns[0][1] If $iIDFrom = $Mns[$i][$j] Then MsgBox(0x40, 'Menu Message!', 'From button: #' & $i & @LF & 'From menu: #' & $j+1) ExitLoop(2) EndIf Next Next EndFunc ';] Tekkion 1
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