Jump to content

[Solved] Show a ContextMenu in response to a HotKey


Zohar
 Share

Recommended Posts

Hello

I have a very small ContextMenu that I created:

Local   $ContextMenu            =GUICtrlCreateContextMenu()
Local   $ContextMenu_Option1    =GUICtrlCreateMenuItem("Option1",$ContextMenu)
Local   $ContextMenu_Option2    =GUICtrlCreateMenuItem("Option2",$ContextMenu)
Local   $ContextMenu_Option3    =GUICtrlCreateMenuItem("Option3",$ContextMenu)

and I would like it to be Shown, If the user presses F7,

for whatever application is currently active.

So no matter if right now you work on Notepad, or Outlook, or whatever, this small ContextMenu will be shown for an F7 press.

How do I do it?

Edited by Zohar
Link to comment
Share on other sites

In my quick research, you may need to make a GUI with the list of items you want, then have it be positioned by using MouseGetPos. That way you can use F7 as a HotSetKey

oh no :[

I really hope there's a way to do it, and not to create a window that looks like a menu.. :unsure:

Link to comment
Share on other sites

Maybe...

HotKeySet("{ESC}", "Terminate")
HotKeySet("{F7}", "Context")

While 1
    Sleep(100) ; always a good idea so you dont max your cpu

WEnd

Func Terminate()
    Exit 0
EndFunc   ;==>Terminate

Func Context()
    MouseClick("secondary")
EndFunc   ;==>Context

[u]Helpful tips:[/u]If you want better answers to your questions, take the time to reproduce your issue in a small "stand alone" example script whenever possible. Also, make sure you tell us 1) what you tried, 2) what you expected to happen, and 3) what happened instead.[u]Useful links:[/u]BrettF's update to LxP's "How to AutoIt" pdfValuater's Autoit 1-2-3 Download page for the latest versions of Autoit and SciTE[quote]<glyph> For example - if you came in here asking "how do I use a jackhammer" we might ask "why do you need to use a jackhammer"<glyph> If the answer to the latter question is "to knock my grandmother's head off to let out the evil spirits that gave her cancer", then maybe the problem is actually unrelated to jackhammers[/quote]

Link to comment
Share on other sites

From the helpfile. Your only choice is to do it this way. Look at what I highlighted in RED below :

GUICtrlCreateContextMenu

--------------------------------------------------------------------------------

Creates a context menu for a control or entire GUI window.

GUICtrlCreateContextMenu ( [controlID] )

Parameters

controlID [optional] Control identifier as returned by GUICtrlCreate...

Return Value

Success: Returns the identifier (controlID) of the new control.

Failure: Returns 0.

Remarks

After creating the context menu main control with this function, each menu item can be created by using GUICtrlCreateMenuItem.

Sub-menus can be created using GUICtrlCreateMenu.

If you use no parameters or -1 in this function then the context menu that is created is associated with the entire GUI window rather than an individual control.

Only one context menu per control is possible. If you wish to create a new context menu one you have to delete the existing menu first.

Note: You can't create context menus for controls that already have system context menus, i.e. edit or input controls.

Link to comment
Share on other sites

Spook:

thank you for that solution,

however this ContextMenu is not really in Context of any Window,

it's an independent ContextMenu..

so Simulating a RightClick will not show it..

Volly:

I am not trying to create a ContextMenu for a certain Control.

I am simply using this ContextMenu as a simple GUI to enable the user choose some options, in response to F7.

After that F7 press, this menu should not be connected in any way, with any control, on the current window.

So I hope someone might have a creative idea of how to open it..

Edited by Zohar
Link to comment
Share on other sites

This is not important :P you can open a popupmenu everywhere this way:

#include <GUIMenu.au3>
#include <windowsconstants.au3>

$GUI = GUICreate("",1,1,-10,-10,$WS_POPUP,$WS_EX_TOOLWINDOW)
GUISetState()
$Context = GUICtrlCreateContextMenu()
$hContext = GUICtrlGetHandle($Context)

$test = GUICtrlCreateMenuItem("test",$Context)

HotKeySet("{F7}","_HK")

While 1
    Switch GUIGetMsg()
        Case $test
            MsgBox(0, '', "")
    EndSwitch
WEnd

Func _HK()
    $ActiveWin = WinGetHandle("")
    WinActivate($GUI)
    _GUICtrlMenu_TrackPopupMenu($hContext,$GUI)
    WinActivate($ActiveWin)
EndFunc

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

Here is an example on how to do it as I suggested.

#include <GUIConstants.au3>
#include <WindowsConstants.au3>

HotKeySet("{ESC}", "Terminate")
HotKeySet("{F7}", "Context")
DIM $Form1, $Label_1, $Label_2, $Label_3
$Form1 = GUICreate("", 100, 75, 193, 80, BitOR($WS_POPUP, $WS_EX_MDICHILD,$WS_EX_TOOLWINDOW))
$Label_1 = GUICtrlCreateLabel("Notepad", 8, 5, 45, 17)
$Label_2 = GUICtrlCreateLabel("Msgbox", 8, 27, 41, 17)
$Label_3 = GUICtrlCreateLabel("Calculator", 8, 48, 51, 17)
GUISetState(@SW_Hide)

While 1
    $Msg = GUIGetMsg(0)
    select 
        Case $Msg = $GUI_EVENT_CLOSE
            Exit
        Case $Msg = $Label_1
            GUISetState(@SW_HIDE)
            Run("Notepad.exe")
        Case $Msg = $Label_2
            GUISetState(@SW_HIDE)
            MsgBox(0, "Item Selected", "You clicked the messagebox menu item")
        Case $Msg = $Label_3
            GUISetState(@SW_HIDE)
            Run("Calc.exe")
    EndSelect
WEnd

Func Terminate()
    Exit 0
EndFunc   ;==>Terminate

Func Context()
    $m = MouseGetPos()
    WinMove($Form1, "", $m[0], $m[1])
    GUISetState(@SW_SHOW,$Form1)
EndFunc   ;==>Context
Link to comment
Share on other sites

looks cool(and not as horrible as I feared).

btw you could've used some List control(ListView/ListBox/etc), it would've made the code even shorter,

and would've spared you from the need to align the Labels..

BTW..

Do you know why the makers of AutoIt did not update the DLL of it to be a .NET DLL?

That way it would've been possible to use all the good stuff of the .NET Framework, plus AutoIt's features..

Edited by Zohar
Link to comment
Share on other sites

Some nice methods there. I followed another approach, it's more difficult to do and requires more hotkeys, but it has the advantage that it doesn't steal focus from the other windows (especially useful for fullscreen games) It uses tooltips, so no real gui !!

It's unfinished, but you can see the "proof of concept". For testing, just run the script,use F7 to open the menu and press down to choose the next option. The "menu" will close itself after 3 seconds of inactivity. Exit script via the tray.

I haven't implemented code to the options, yet, but it's easy to do.

Dim $option [6] = [5,1,0,0,0,0]    ; member [0] is the number of options, 5 in this example. 4 normal options and the Exit option
$tooltip_active = 0
$reset = 5000     ; insignificant initial value

HotKeySet ("{F7}","OpenMenu")
HotKeySet ("{DOWN}","UpdateMenu")
;it will probably need more hotkeys for UP, for selecting an option etc.   :-/

while 1
    Sleep (1000)
    If TimerDiff ($reset) > 3000 Then
        ToolTip("")
        $tooltip_active = 0
    EndIf       
WEnd    

Func OpenMenu ()
    $Pos = MouseGetPos ()
    Tooltip (CheckOption(1)&"Option 1"&@LF&CheckOption(2)&"Option 2"&@LF&CheckOption(3)&"Option 3"&@LF&CheckOption(4)&"Option 4"&@LF&CheckOption(5)&"Exit !", ($Pos[0]+20), ($Pos[1]+20))
    $tooltip_active = 1
    $reset = TimerInit ()
EndFunc 

Func CheckOption ($opt_number)
    If $option[$opt_number] = 1 Then
        return "~"
    Else
        return "   "
    EndIf
EndFunc 

Func UpdateMenu ()
    For $i = 1 To ($option[0] - 1)
        If $option[$i] = 1 Then
            $option[$i] = 0
            $option[($i+1)] = 1
            OpenMenu ()
            Return
        EndIf
    Next
    $option[$i] = 0
    $option[1] = 1
    OpenMenu ()
    Return
EndFunc

Kinda weird, huh ?

Edited by Inverted
Link to comment
Share on other sites

Here is another tweak. I used _IsPressed to use the CTRL key and secondary mouse click to do it. This method is more comfortable for the user for it simply has the user hold down the CTRL key when secondary mouse clicking to get the context menu.

#include <Misc.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>

HotKeySet("{ESC}", "Terminate")
$dll = DllOpen("user32.dll")
DIM $Form1, $Label_1, $Label_2, $Label_3
$Form1 = GUICreate("", 100, 75, 193, 80, BitOR($WS_POPUP, $WS_EX_MDICHILD,$WS_EX_TOOLWINDOW))
$Label_1 = GUICtrlCreateLabel("Notepad", 8, 5, 45, 17)
$Label_2 = GUICtrlCreateLabel("Msgbox", 8, 27, 41, 17)
$Label_3 = GUICtrlCreateLabel("Calculator", 8, 48, 51, 17)
GUISetState(@SW_Hide)

While 1
    $Msg = GUIGetMsg(0)
    select
        Case _IsPressed("02", $dll) and _IsPressed("11", $dll)
            Context()
            while 2
                $Msg2 = GUIGetMsg(0)
                Select 
                    Case $Msg2 = $GUI_EVENT_CLOSE
                        Exit
                    Case $Msg2 = $Label_1
                        GUISetState(@SW_HIDE)
                        Run("Notepad.exe")
                        ExitLoop
                    Case $Msg2 = $Label_2
                        GUISetState(@SW_HIDE)
                        MsgBox(0, "Item Selected", "You clicked the messagebox menu item")
                        ExitLoop
                    Case $Msg2 = $Label_3
                        GUISetState(@SW_HIDE)
                        Run("Calc.exe") 
                        ExitLoop
                EndSelect   
            WEnd
        Case $Msg = $GUI_EVENT_CLOSE
            Exit            
    EndSelect
WEnd

Func Terminate()
    Exit 0
EndFunc   ;==>Terminate

Func Context()
    $m = MouseGetPos()
    WinMove($Form1, "", $m[0], $m[1])
    GUISetState(@SW_SHOW,$Form1)
EndFunc   ;==>Context
Edited by Volly
Link to comment
Share on other sites

Here is one with a combo box. I like this better. It could be done with a INI file to allow for easy adding of items and paths.

#include <Misc.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>

HotKeySet("{ESC}", "Terminate")
$dll = DllOpen("user32.dll")
$Form1  = GUICreate("", 100, 22, 193, 80, BitOR($WS_POPUP, $WS_EX_MDICHILD,$WS_EX_TOOLWINDOW))
$List_1 = GUICtrlCreateCombo("", 0, 0, 100, 22)
GUICtrlSetData($List_1, "Notepad|Calculator|Word|FireFox|SciTE","")
WinSetOnTop($Form1, "", 1)
GUISetState(@SW_Hide)

While 1
    $Msg = GUIGetMsg(0)
    select
        Case _IsPressed("02", $dll) and _IsPressed("11", $dll)
            Context()
            while 2
                $Msg2 = GUIGetMsg(0)
                Select 
                    Case $Msg2 = $GUI_EVENT_CLOSE
                        Exit
                    Case $Msg2 = $List_1
                    $G = GUICtrlRead($List_1)
                    If $G = "Notepad" then 
                        GUISetState(@SW_HIDE)
                        Run("Notepad.exe")
                        ExitLoop
                    endif
                    If $G = "Calculator" then 
                        GUISetState(@SW_HIDE)
                        Run("Calc.exe")
                        ExitLoop
                    endif
                    If $G = "Word" then 
                        GUISetState(@SW_HIDE)
                        Run("C:\Program Files\Microsoft Office\OFFICE11\WINWORD.EXE")
                        ExitLoop
                    endif   
                    If $G = "FireFox" then 
                        GUISetState(@SW_HIDE)
                        Run("C:\Program Files\Mozilla Firefox\firefox.exe")
                        ExitLoop
                    endif   
                    If $G = "SciTE" then 
                        GUISetState(@SW_HIDE)
                        Run("C:\Program Files\AutoIt3\SciTE\SciTE.exe")
                        ExitLoop
                    endif   
                EndSelect   
            WEnd
        Case $Msg = $GUI_EVENT_CLOSE
            Exit            
    EndSelect
WEnd

Func Terminate()
    Exit 0
EndFunc   ;==>Terminate

Func Context()
    $m = MouseGetPos()
    WinMove($Form1, "", $m[0], $m[1])
    GUISetState(@SW_SHOW,$Form1)
EndFunc   ;==>Context
Link to comment
Share on other sites

Because AutoIt is made with C++, not .NET.

porting the source code of AutoIt from C++ to C# should not be too hard, since the 2 languages have similar syntax,

and C# offers much easier coding, much nicer set of classes to help the developer, etc etc.

.NET is with us since 2001,

it's now 2009..

I don't understand why the makers of AutoIt choose not to enjoy all the benefits and speed of coding that C# offers.

Link to comment
Share on other sites

porting the source code of AutoIt from C++ to C# should not be too hard, since the 2 languages have similar syntax,

and C# offers much easier coding, much nicer set of classes to help the developer, etc etc.

.NET is with us since 2001,

it's now 2009..

I don't understand why the makers of AutoIt choose not to enjoy all the benefits and speed of coding that C# offers.

C# is shit for autoit's purpose , it requires .NET Framework.
Link to comment
Share on other sites

Inverted:

The .NET framework exists on every Windows machine nowdays..

and even if there's 1 without it, it's 20MB, available for Download..

the same way you downloaded AutoIt..

And it's not shit at all..

If you compare writing code in .NET(C#), compared to writing code in AutoIt Script,

I can truely tell you, AutoIt Script is hardddddddd for many things that in .NET you do in 5 seconds..

If AutoIt's Library would've been ported to be a .NET library instead of a COM one,

people could enjoy both worlds:

Enjoying the benefits of AutoIt, and enjoying the benefits of writing in .NET.

In addition micrisoft gives Visual Studio Express Edition for Free,

which is a fantastic development environment, that has everything you need,

with a great AutoComplete(IntelliSense) mechanism to speed your code.

Most of you guys resist .NET and call it "shit" because you haven't tried it.

If you had, you would've begged Jon to change AutoIt to be a .NET library.

But it's the natrual tendency of people to believe that what they currently do is the best,

and not to try other options, that sometimes might be overwhelmingly better.

regarding your code example:

it has the advantage that it doesn't steal focus from the other windows (especially useful for fullscreen games) It uses tooltips, so no real gui !!

very interesting idea..

you implemented it that way because the main thing you needed is for the game not to lose focus?

it was that critical?

Edited by Zohar
Link to comment
Share on other sites

very interesting idea..

you implemented it that way because the main thing you needed is for the game not to lose focus?

it was that critical?

I wrote it today for your post actually. That's why it's not finished yet.

I wrote it that way because I'm not very experienced with GUIs. It's kinda cool, huh ? Imagine a game trainer supporting options like that ingame :P

Edited by Inverted
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...