Sign in to follow this  
Followers 0
Sunaj

Call forth ContextMenu

7 posts in this topic

Hi, I'm trying to make a script that, via a hotkey, calls forth a ContextMenu anywhere on the screen (for manipulating text..etc.). Now the issue is how to allow a hotkey to be shown anywhere - without it being limited to a specific GUI or control. The following code mashup frm the helpfile on GUICtrlCreateContextMenu is what I got so far - it might work if I could get the GUI hidden away and the "TrackPopupMenu" function to show the ContextMenu at the mouse cursor location. However I still believe it would be better if the context menu could be called via a more 'clean' hack! Thanks for your help!

#include <GUIConstants.au3>
Opt("GUIOnEventMode", 1)  ; change to onevent mode

HotKeySet("^t", "OptionsBtn")

$hGui           = GUICreate("My GUI", 70, 20,-1,-1,$WS_POPUPWINDOW)
$OptionsBtn     = GUICtrlCreateButton("&Options", 0, 0, 70, 20, $BS_FLAT)
GUICtrlSetOnEvent ($OptionsBtn,"OptionsBtn")
$OptionsDummy   = GUICtrlCreateDummy()
$OptionsContext = GUICtrlCreateContextMenu($OptionsDummy)
$OptionsCommon  = GUICtrlCreateMenuItem("Common", $OptionsContext)
$OptionsFile    = GUICtrlCreateMenuItem("File", $OptionsContext)
GUICtrlCreateMenuItem("", $OptionsContext)
$OptionsExit    = GUICtrlCreateMenuItem("Exit", $OptionsContext)
GUICtrlSetOnEvent ($OptionsExit,"OptionsExit")

;GUICtrlSetPos ( controlID, left, top [, width [, height]] )
;$pos = MouseGetPos()

GUISetState()

While 1
    Sleep(500)
WEnd

Exit

Func OptionsBtn()
    ;MsgBox(4096, "data", $OptionsBtn)
    ;MsgBox(4096, "data", $hGui)
    ShowMenu($hGui, $OptionsBtn, $OptionsContext)
EndFunc

Func OptionsExit()
    Exit
EndFunc

; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $CtrlID, $nContextID)
    Local $hMenu = GUICtrlGetHandle($nContextID)
    
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
    
    Local $x = $arPos[0]
    Local $y = $arPos[1] + $arPos[3]
    
    ClientToScreen($hWnd, $x, $y)
    TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc


; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
    Local $stPoint = DllStructCreate("int;int")
    
    DllStructSetData($stPoint, 1, $x)
    DllStructSetData($stPoint, 2, $y)

    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "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($hWnd, $hMenu, $x, $y)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc

Share this post


Link to post
Share on other sites



Do you mean like this?

#include <GUIConstants.au3>
Opt('GUIOnEventMode', 1)
HotKeySet("^t", "OptionsBtn")
$hGui         = GUICreate("My GUI", 70, 20,-1, -1, -1, 0x00000080)
$OptionsLabel = GUICtrlCreateLabel('', 10, 10)
$OptionsDummy   = GUICtrlCreateDummy()
$OptionsContext = GUICtrlCreateContextMenu($OptionsDummy)
$OptionsCommon  = GUICtrlCreateMenuItem("Common", $OptionsContext)
$OptionsFile    = GUICtrlCreateMenuItem("File", $OptionsContext)
GUICtrlCreateMenuItem("", $OptionsContext)
$OptionsExit    = GUICtrlCreateMenuItem("Exit", $OptionsContext)
GUICtrlSetOnEvent ($OptionsExit,"OptionsExit")
WinSetTrans($hGui, '', 0)
GUISetState()

While 1
    Sleep(500)
WEnd

Exit

Func OptionsBtn()
    ;MsgBox(4096, "data", $OptionsBtn)
    ;MsgBox(4096, "data", $hGui)
    ShowMenu($hGui, $OptionsLabel, $OptionsContext)
EndFunc

Func OptionsExit()
    Exit
EndFunc

; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $CtrlID, $nContextID)
    Local $hMenu = GUICtrlGetHandle($nContextID)
   
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
   
    Local $x = $arPos[0]
    Local $y = $arPos[1] + $arPos[3]
   
    ClientToScreen($hWnd, $x, $y)
    TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc


; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
    Local $stPoint = DllStructCreate("int;int")
   
    DllStructSetData($stPoint, 1, $x)
    DllStructSetData($stPoint, 2, $y)

    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "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($hWnd, $hMenu, $x, $y)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Yes, exactly like that, only I also need the menu to show up exactly where the mouse cursor is :lmao: Thanks f your help!

Do you mean like this?

.... 
#include <GUIConstants.au3>
Opt('GUIOnEventMode', 1)
HotKeySet("^t", "OptionsBtn")
$hGui         = GUICreate("My GUI", 70, 20,-1, -1, -1, 0x00000080)
$OptionsLabel = GUICtrlCreateLabel('', 10, 10)
$OptionsDummy   = GUICtrlCreateDummy()
$OptionsContext = GUICtrlCreateContextMenu($OptionsDummy)
$OptionsCommon  = GUICtrlCreateMenuItem("Common", $OptionsContext)
$OptionsFile    = GUICtrlCreateMenuItem("File", $OptionsContext)
GUICtrlCreateMenuItem("", $OptionsContext)
....
Edited by Sunaj

Share this post


Link to post
Share on other sites

Yes, exactly like that, only I also need the menu to show up exactly where the mouse cursor is :lmao: Thanks f your help!

#include <GUIConstants.au3>
Opt('GUIOnEventMode', 1)
HotKeySet("^t", "OptionsBtn")
$hGui         = GUICreate("My GUI", 70, 20,-1, -1, -1, 0x00000080)
$OptionsLabel = GUICtrlCreateLabel('', 10, 10)
$OptionsDummy   = GUICtrlCreateDummy()
$OptionsContext = GUICtrlCreateContextMenu($OptionsDummy)
$OptionsCommon  = GUICtrlCreateMenuItem("Common", $OptionsContext)
$OptionsFile    = GUICtrlCreateMenuItem("File", $OptionsContext)
GUICtrlCreateMenuItem("", $OptionsContext)
$OptionsExit    = GUICtrlCreateMenuItem("Exit", $OptionsContext)
GUICtrlSetOnEvent ($OptionsExit,"OptionsExit")
WinSetTrans($hGui, '', 0)
GUISetState()

While 1
    Sleep(500)
WEnd

Exit

Func OptionsBtn()
    ;MsgBox(4096, "data", $OptionsBtn)
    ;MsgBox(4096, "data", $hGui)
    Local $aMPos = MouseGetPos()
    If IsArray($aMPos) Then WinMove(HWnd($hGui), '', $aMPos[0] - 20, $aMPos[1] - 50)
    ShowMenu($hGui, $OptionsLabel, $OptionsContext)
EndFunc

Func OptionsExit()
    Exit
EndFunc

; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $CtrlID, $nContextID)
    Local $hMenu = GUICtrlGetHandle($nContextID)
   
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
   
    Local $x = $arPos[0]
    Local $y = $arPos[1] + $arPos[3]
   
    ClientToScreen($hWnd, $x, $y)
    TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc


; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
    Local $stPoint = DllStructCreate("int;int")
   
    DllStructSetData($stPoint, 1, $x)
    DllStructSetData($stPoint, 2, $y)

    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "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($hWnd, $hMenu, $x, $y)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

Yep, that's it, I like the WinMove solution, very simple & functional! I hope I'm not over-questioning here: Any idea how to make the menu behave so that if I bring it up (ctrl-t) and then click -outside- it, it'll make it disappear again?! (I can guarantee something useful in the Scripts and Scraps forum if i can make this work)

#include <GUIConstants.au3>
Opt('GUIOnEventMode', 1)
HotKeySet("^t", "OptionsBtn")
$hGui         = GUICreate("My GUI", 70, 20,-1, -1, -1, 0x00000080)
$OptionsLabel = GUICtrlCreateLabel('', 10, 10)
$OptionsDummy   = GUICtrlCreateDummy()
$OptionsContext = GUICtrlCreateContextMenu($OptionsDummy)
$OptionsCommon  = GUICtrlCreateMenuItem("Common", $OptionsContext)
$OptionsFile    = GUICtrlCreateMenuItem("File", $OptionsContext)
GUICtrlCreateMenuItem("", $OptionsContext)
$OptionsExit    = GUICtrlCreateMenuItem("Exit", $OptionsContext)
GUICtrlSetOnEvent ($OptionsExit,"OptionsExit")
WinSetTrans($hGui, '', 0)
GUISetState()

While 1
    Sleep(500)
WEnd

Exit

Func OptionsBtn()
    ;MsgBox(4096, "data", $OptionsBtn)
    ;MsgBox(4096, "data", $hGui)
    Local $aMPos = MouseGetPos()
    If IsArray($aMPos) Then WinMove(HWnd($hGui), '', $aMPos[0] - 20, $aMPos[1] - 50)
    ShowMenu($hGui, $OptionsLabel, $OptionsContext)
EndFunc

Func OptionsExit()
    Exit
EndFunc

; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $CtrlID, $nContextID)
    Local $hMenu = GUICtrlGetHandle($nContextID)
   
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
   
    Local $x = $arPos[0]
    Local $y = $arPos[1] + $arPos[3]
   
    ClientToScreen($hWnd, $x, $y)
    TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc
; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
    Local $stPoint = DllStructCreate("int;int")
   
    DllStructSetData($stPoint, 1, $x)
    DllStructSetData($stPoint, 2, $y)

    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "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($hWnd, $hMenu, $x, $y)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Yep, that's it, I like the WinMove solution, very simple & functional! I hope I'm not over-questioning here: Any idea how to make the menu behave so that if I bring it up (ctrl-t) and then click -outside- it, it'll make it disappear again?! (I can guarantee something useful in the Scripts and Scraps forum if i can make this work)

Ok, I got that feature nailed through a bit of creative trial&error! :lmao: Below is code that may be used to make a 'universal' system context menu appear in any and all applications incl. windows taskbar..etc. Right now the code does not do anything but should serve as an ok template. Please note the location of the GUISetState(@SW_RESTORE,$hGui) & the GUICreate parameters since they are both critical to get the "click-outside-makes-menu-disappear" feature to work.

#include <GUIConstants.au3>
Opt('GUIOnEventMode', 1)
HotKeySet("^t", "OptionsLabel")
$hGui           = GUICreate("HiddenMasterMenu", 70, 20,-1, -1, -1, $WS_EX_TOPMOST + 0x00000080) ; only combination that seems to work right
$OptionsLabel   = GUICtrlCreateLabel('', 10, 10)
$OptionsDummy   = GUICtrlCreateDummy()
$OptionsContext = GUICtrlCreateContextMenu($OptionsDummy)
$OptionsCommon  = GUICtrlCreateMenuItem("Common", $OptionsContext)
$OptionsFile    = GUICtrlCreateMenuItem("File", $OptionsContext)
GUICtrlCreateMenuItem("", $OptionsContext)
$OptionsExit    = GUICtrlCreateMenuItem("Exit", $OptionsContext)
GUICtrlSetOnEvent ($OptionsExit,"OptionsExit")
WinSetTrans($hGui, '', 0)
GUISetState()

While 1
    Sleep(500)
WEnd

Exit

Func OptionsLabel()
    GUISetState(@SW_RESTORE,$hGui) ; important to make focus work right
    Local $aMPos = MouseGetPos()
    If IsArray($aMPos) Then WinMove(HWnd($hGui), '', $aMPos[0] - 13, $aMPos[1] - 40)
    ShowMenu($hGui, $OptionsLabel, $OptionsContext)
EndFunc

Func OptionsExit()
    Exit
EndFunc

; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $CtrlID, $nContextID)
    Local $hMenu = GUICtrlGetHandle($nContextID)
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
    Local $x = $arPos[0]
    Local $y = $arPos[1] + $arPos[3]
    ClientToScreen($hWnd, $x, $y)
    TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc


; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
    Local $stPoint = DllStructCreate("int;int")
    DllStructSetData($stPoint, 1, $x)
    DllStructSetData($stPoint, 2, $y)
    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
    $x = DllStructGetData($stPoint, 1)
    $y = DllStructGetData($stPoint, 2)
EndFunc


; 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)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc
Edited by Sunaj

Share this post


Link to post
Share on other sites

Very good!

Well done Sunaj and SmOke N


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.

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0