Jump to content

Dynamic Menu creation using ini file


Mjolnir
 Share

Recommended Posts

Hello all,

Using since a long time AutoIt, here my first participation in this forum, hope this helps...

Here is a quick dynamic menu creation under right mouse click button, on any file/folder, using a simple ini file for list of "programs" to run.

Usage of myFloatingMenu is simple : once compiled (or not), it reads the ini file, and create a dynamic menu under user's cursor, each menu line corresponding to a [Menu_Line_XX] section from ini file.

Command line option :

  • myFloatingMenu.exe (call menu under user's cursor)
  • myFloatingMenu.exe <file name>|<foldername> (call menu, with parameter as current file/folder, usable via #CMDLINEx# parameters in ini file)
  • myFloatingMenu.exe /AddReg (Add current menu in registry, using ini RegKey=)
  • myFloatingMenu.exe /AddReg:"my_key" (Add current menu in registry)<BR><TAB>- myFloatingMenu.exe /DelReg (Delete current menu from registry)

The trick is, once added in registry (using /AddReg option on command line), this FloatingMenu is available for any right mouse click, on file/folder, to perform <your> specific action(s) described in the ini file :)

Enjoy...

---

Ini configuration is relatively easy : simply add in ini file list of [Menu_Line_XX] sections, that will cointain :

  • Title = title of menu that will be created
  • Command = program to execute
  • Options = option on "command" command line

Here myFloatingMenu.ini file:

#~ -------------------------------------------------8<-------------------------------------------------
#~ [Default_Config]
#~ Debug        = [0|1]  (to activate "debug" mode, default value = 0)
#~ Revision     = <any text> (your own revision of current ini file)
#~ MenuRegKey   = "<any text, may contain a &>" (name of menu entry [in registry + for right click mouse button on any file/folder], default value is = "  + my&FloatingMenu...")
#~ Menu_Lines   = <a number> (it's the number of menu(s) line(s) to take into account below ... ie, number of [Menu_Line_<1-99>] sections to read, to create the dynamic menu)
#~ -------------------------------------------------8<-------------------------------------------------

[Default_Config]
Debug       = 0
Revision    = A.01
MenuRegKey  ="  + my&FloatingMenu..."
Menu_Lines  = 14




#~ -------------------------------------------------8<-------------------------------------------------
#~ [Menu_Line_<1-99>]
#~ Title    = <-> or <Menu Title> or <Menu Title #Options# (and #Options# will be replaced by value of "Options=")> or <Menu Title without "Command=" and without "Option=" (= perform an EXIT)> or <Menu Title with "Options=" only, could contain <BR><HR><TAB> = to show a popup with "Options" as text>
#~ Command  = <full command line to exe, without quotes (")> or <leave empty>
#~ Options  = <possible command line option(s) for "Command=">... can use too : <#CMDLINE1#, #CMDLINE2# or #CMDLINE3# or \"#CMDLINE1#\", as parameters taken from script command line> or <leave empty>
#~ -------------------------------------------------8<-------------------------------------------------

[Menu_Line_1]
Title   = Start Explorer
Command = c:\WINDOWS\explorer.exe


[Menu_Line_2]
Title   = Start Explorer on \"c:\Documents and Settings\"
Command = c:\WINDOWS\explorer.exe
Options = \"c:\Documents and Settings"\


[Menu_Line_3]
Title   = Start Explorer, taking first option on script command line (/e,/root,#CMDLINE1#)
Command = explorer.exe
Options = /e,/root,\"#CMDLINE1#\"


[Menu_Line_4]
Title   = -


[Menu_Line_5]
Title   = Start Internet Explorer (#Options#)
Command = c:\Program Files\Internet Explorer\iexplore.exe
Options = http://www.google.com


[Menu_Line_6]
Title   = -


[Menu_Line_7]
Title   = Start Notepad
Command = notepad


[Menu_Line_8]
Title   = Start Notepad (on file : #Options#)
Command = notepad
Options = #CMDLINE1#


[Menu_Line_9]
Title   = Excel (with doc. givent as 1st command line parameter)
Command = c:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE
Options = \"#CMDLINE1#\"


[Menu_Line_10]
Title   = -


[Menu_Line_11]
Title   = About...
Options = About example popup message box<BR>(c) 04/2011<BR><HR><BR>myFloatingMenu.exe is my Dynamic Menu "tool", using a .ini file<BR>for list of programes/actions to perform...


[Menu_Line_12]
Title   = myFloatingMenu.exe usage...
Options = Syntaxe usage is<BR><TAB>- myFloatingMenu.exe    (call menu)<BR><TAB>- myFloatingMenu.exe <file name>|<foldername>   (call menu, with parameter as current file/folder, usable via #CMDLINEx# parameters in ini file)<BR><TAB>- myFloatingMenu.exe /AddReg   (Add current menu in registry, using ini RegKey=)<BR><TAB>- myFloatingMenu.exe /AddReg:"my_key"   (Add current menu in registry)<BR><TAB>- myFloatingMenu.exe /DelReg   (Delete current menu from registry)


[Menu_Line_13]
Title   = Help example...
Options = Usage is :<BR><TAB>- Select a menu option to execute command<BR><TAB>- or press [Esc] to "exit" the menu


[Menu_Line_13]
Title   = Nothing as [Menu_Line_13] is duplicated from previous one ! (only first [Menu_Line_xx] occurrence count)


[Menu_Line_14]
Title   = -Exit menu option-


[Menu_Line_15]
Title   = Nothing as out of "Menu_Lines" number...

[Menu_Line_16]
Title   = Nothing as out of "Menu_Lines" number...

Here the au3 script

; -----------------------------------8<-----------------------------------
; myFloatingMenu - Mjr. 04/2011 - Rev E.07
; -----------------------------------8<-----------------------------------
#include <array.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>


; -----------------------------------8<-----------------------------------
$Ini_File               = StringReplace(StringReplace(@ScriptFullPath,".au3",".ini"),".exe",".ini")
; -----------------------------------8<-----------------------------------
$DEBUG                  = IniRead($Ini_File, "Default_Config", "DEBUG",     0)
If $DEBUG = 1 Then
    $DEBUG = True
Else
    $DEBUG = False
EndIf
$Menu_Lines             = IniRead($Ini_File, "Default_Config", "Menu_Lines",0)
; -----------------------------------8<-----------------------------------
$HRValue                = "---"
; -----------------------------------8<-----------------------------------
$Title                  = StringReplace(StringReplace(@ScriptName,".au3",""),".exe","")
$Rev                    = IniRead($Ini_File, "Default_Config", "Revision",  0)
$Title                  = $Title & " - " & $Rev
; -----------------------------------8<-----------------------------------




; -----------------------------------8<-----------------------------------
; Registry FloatingMenu /RegAdd or /RegDel ?
If $CmdLine[0] = 1 Then
    If StringUpper(StringLeft($CmdLine[1],7)) = "/REGADD" or StringUpper(StringLeft($CmdLine[1],7)) = "/ADDREG" Then

        ; Get /RegAdd:"menu title to add in Registry"
        $RegKey = IniRead($Ini_File, "Default_Config", "MenuRegKey",    "  + my&FloatingMenu...")
        If $RegKey = "  + my&FloatingMenu..." Then
            $RegKey = StringMid($CmdLine[1],9)
            If StringLen($RegKey) = 0 Then $RegKey = "  + my&FloatingMenu..."
        EndIf

        ; Add current Script to Registry, on any File/Folder right mouse click menu
        $RetVal = RegWrite("HKEY_CLASSES_ROOT\*\shell\" & $RegKey & "\command","","REG_SZ",@ScriptFullPath & ' "%l"')
        $RetVal = $RetVal + RegWrite("HKEY_CLASSES_ROOT\Folder\shell\" & $RegKey & "\command","","REG_SZ",@ScriptFullPath & ' "%l"')
        If $RetVal = 2 Then
            MSgBox(0+64,$Title,"Successfully added key [" & $RegKey & "] in registry, for any file/folder mouse right button menu.")
        Else
            MSgBox(0+48,$Title,"Impossible to add in registry the key [" & $RegKey & "]")
        EndIf

        IniWrite($Ini_File, "Default_Config", "MenuRegKey", Chr(34) & $RegKey & Chr(34))

        Exit

    ElseIf StringUpper(StringLeft($CmdLine[1],7)) = "/REGDEL" or  StringUpper(StringLeft($CmdLine[1],7)) = "/DELREG" Then

        ; Get /RegDel:"menu title to delete from Registry"
        $RegKey = StringMid($CmdLine[1],9)
        If StringLen($RegKey) = 0 Then
            ; $RegKey = "  + myFloatingMenu..."
            $RegKey = IniRead($Ini_File, "Default_Config", "MenuRegKey",    "  + my&FloatingMenu...")
        EndIf

        ; Remove current Script from Registry, for any File/Folder right mouse click menu
        $RetVal = RegDelete("HKEY_CLASSES_ROOT\*\shell\" & $RegKey)
        $RetVal = $RetVal + RegDelete("HKEY_CLASSES_ROOT\Folder\shell\" & $RegKey)
        If $RetVal = 2 Then
            MSgBox(0+64,$Title,"Successfully deleted from registry key [" & $RegKey & "], for any file/folder mouse right button menu.")
        Else
            MSgBox(0+48,$Title,"Impossible to delete from registry the key [" & $RegKey & "]")
        EndIf
        Exit

    EndIf
EndIf
; -----------------------------------8<-----------------------------------




; -----------------------------------8<-----------------------------------
; Create a Menu Array + fill a header (not really necessary...) : Id, Menu title, Command
Local $aMenuRow = 1
Local $aMenuCol = 4
Local $aMenu[$aMenuRow][$aMenuCol]
$aMenu[0][0] = "GUICtrlCreateMenuItem Id"           ; $aMenu[x][0] : Will contain the "Handle" of the "GUICtrlCreateMenuItem" (see function GUIBuildAndShowMenu() )
$aMenu[0][1] = "Menu Title"                         ; $aMenu[x][1] : Will contain the "Title" from ini file   (see function BuildaMenuArray() )
$aMenu[0][2] = "Command"                            ; $aMenu[x][2] : Will contain the "Command" from ini file (see function BuildaMenuArray() )
$aMenu[0][3] = "Options"                            ; $aMenu[x][3] : Will contain the "Options" from ini file (see function BuildaMenuArray() )



; -----------------------------------8<-----------------------------------
; (only) Parse ini file to fill the Menu array with Title + Command + Options
BuildaMenuArray()


; -----------------------------------8<-----------------------------------
; Build & shouw the GUI menu (& fill the last empty column $aMenu[x][0] with the currently created MenuItem "handles")
GUIBuildAndShowMenu()

; -----------------------------------8<-----------------------------------
; Wait in loop user's "menu choice", and execute the selected command
GUIWaitUserMenuSelectionAndExecuteCommand()


Exit
; -----------------------------------8<-----------------------------------




; -----------------------------------8<-----------------------------------
; (only) Parse ini file to fill the Menu array with Title + Command + Options
Func BuildaMenuArray()
    For $mId = 1 to $Menu_Lines
        $aMenuRow = $aMenuRow + 1
        ReDim $aMenu[$aMenuRow][$aMenuCol]
        $aMenu[$mId][0] = "<Empty at this step, will be GUICtrlCreateMenuItem()>"
        $aMenu[$mId][1] = StringReplace( IniRead($Ini_File, "Menu_Line_" & $mId, "Title",   "") ,'\"',Chr(34))
        $aMenu[$mId][2] = StringReplace( IniRead($Ini_File, "Menu_Line_" & $mId, "Command", "") ,'\"',"")
        $aMenu[$mId][3] = StringReplace( IniRead($Ini_File, "Menu_Line_" & $mId, "Options", "") ,'\"',Chr(34))
        ; Below... replace in "Options", any #CMDLINEx# by the current script $CmdLine[X] value(s)
        ; Not really efficient, as only takes 3x parameters, but works ;-)
        If StringInStr($aMenu[$mId][3],"#CMDLINE1#") <> 0 Then
            If $CmdLine[0] >= 1 Then
                $aMenu[$mId][1] = StringReplace($aMenu[$mId][1],"#CMDLINE1#",$CmdLine[1])
                $aMenu[$mId][3] = StringReplace($aMenu[$mId][3],"#CMDLINE1#",$CmdLine[1])
            Else
                $aMenu[$mId][1] = StringReplace($aMenu[$mId][1],"#CMDLINE1#","")
                $aMenu[$mId][3] = StringReplace($aMenu[$mId][3],"#CMDLINE1#","")
            EndIf
        EndIf
        If StringInStr($aMenu[$mId][3],"#CMDLINE2#") <> 0 Then
            If $CmdLine[0] >= 2 Then
                $aMenu[$mId][1] = StringReplace($aMenu[$mId][1],"#CMDLINE2#",$CmdLine[2])
                $aMenu[$mId][3] = StringReplace($aMenu[$mId][3],"#CMDLINE2#",$CmdLine[2])
            Else
                $aMenu[$mId][1] = StringReplace($aMenu[$mId][1],"#CMDLINE2#","")
                $aMenu[$mId][3] = StringReplace($aMenu[$mId][3],"#CMDLINE2#","")
            EndIf
        EndIf
        If StringInStr($aMenu[$mId][3],"#CMDLINE3#") <> 0 Then
            If $CmdLine[0] >= 3 Then
                $aMenu[$mId][1] = StringReplace($aMenu[$mId][1],"#CMDLINE3#",$CmdLine[3])
                $aMenu[$mId][3] = StringReplace($aMenu[$mId][3],"#CMDLINE3#",$CmdLine[3])
            Else
                $aMenu[$mId][1] = StringReplace($aMenu[$mId][1],"#CMDLINE3#","")
                $aMenu[$mId][3] = StringReplace($aMenu[$mId][3],"#CMDLINE3#","")
            EndIf
        EndIf
        ; Replace #Options# by "Options=" in Menu Title
        $aMenu[$mId][1] = StringReplace( $aMenu[$mId][1], "#Options#",$aMenu[$mId][3])
    Next

    ; -----------------------------------8<-----------------------------------
    If $DEBUG Then _ArrayDisplay($aMenu,"#Debug# - " & $Title & " - " & "aMenu Array created - #Debug#")
EndFunc
; -----------------------------------8<-----------------------------------




; -----------------------------------8<-----------------------------------
; Build & shouw the GUI menu (& fill the last empty column $aMenu[x][0] with the currently created MenuItem "handles")
Func GUIBuildAndShowMenu()
    Local $hGui, $msg
    $pos = MouseGetPos()

    ; Create a GUI window.
    $hGui = GUICreate($Title, 0, 0,-1,-1,$WS_POPUP,BitOR($WS_EX_TOPMOST,$WS_EX_TOOLWINDOW))
    WinMove($Title, "", $pos[0]-3, $pos[1]-3)

    ; Create a dummy control and a contextmenu
    $MenuCtrl = GUICtrlCreateDummy()

    ; Creates a context menu for a control
    $MenuContext    = GUICtrlCreateContextMenu($MenuCtrl)

    ; Add lines in this '$MenuContext' menu & Fill the "last enpty column" $aMenu[x][0] with current GUICtrlCreateMenuItem "handle"
    For $mId = 1 to $Menu_Lines
        If $aMenu[$mId][1] = "-" Then
            $aMenu[$mId][0] = GUICtrlCreateMenuItem("", $MenuContext)
        Else
            $aMenu[$mId][0] = GUICtrlCreateMenuItem($aMenu[$mId][1], $MenuContext)
        EndIf
    Next

    ; Changes the state of a GUI window (default = Hide)
    GUISetState()

    If $DEBUG Then _ArrayDisplay($aMenu,"#Debug# - " & $Title & " - " & "aMenu Array now filled with GUICtrlCreateMenuItem() 'handles' - #Debug#")

    ; Show the menu
    GUIShowMenu($hGui, $msg, $MenuContext)

EndFunc
; -----------------------------------8<-----------------------------------
; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func GUIShowMenu($hWnd, $CtrlID, $nContextID)
    Local $arPos, $x, $y
    Local $hMenu = GUICtrlGetHandle($nContextID)
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
    $x = $arPos[0]
    $y = $arPos[1] + $arPos[3]
    GUIConvertClientToScreen($hWnd, $x, $y)
    GUIShowAndTrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc
; -----------------------------------8<-----------------------------------
; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func GUIConvertClientToScreen($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
; -----------------------------------8<-----------------------------------
; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd)
Func GUIShowAndTrackPopupMenu($hWnd, $hMenu, $x, $y)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc
; -----------------------------------8<-----------------------------------





; -----------------------------------8<-----------------------------------
; Wait in loop user's "menu choice", and execute the selected command
Func GUIWaitUserMenuSelectionAndExecuteCommand()

    ; Loop (parse) "forever" menu until option choosed or [Esc]
    While True

        ; Wait for menu choice
        $msg = GUIGetMsg()

        ; Check for Esc key press
        If $msg = $GUI_EVENT_CLOSE or $msg = 0 Then
            ; Destroy menu & exit
            GUIDelete()
            Exit
        EndIf

        ; Check to execute command... by comparing each $msg to id in aMenu[x][0]
        For $mId = 1 to $Menu_Lines

            ; Found a MenuItem "Handle" matching user's choice... build possible command to execute...
            If $msg = $aMenu[$mId][0] Then

                ; Execute selected menu command...
                $FullCommand = Chr(34) & $aMenu[$mId][2] & Chr(34) & " " & $aMenu[$mId][3]
                If $DEBUG Then MsgBox(0,"#Debug# - " & $Title & " - #Debug#","Selected Menu Item :" & @CR & "- Execute menu id #" & $mId & @CR & "- Title : " & $aMenu[$mId][1] & @CR & "- Command : " & $aMenu[$mId][2] & @CR & "- Option : " & $aMenu[$mId][3] & @CR & "- (Possible) Full executable Command (depending on Command= & Options=) : " & @CR & @TAB & $FullCommand)

                ; If $aMenu[x][2] is empty ("Command="), then, try to show a popup (if $aMenu[$mId][3] ("Options=") is NOT empty) -or- directly exit menu
                If $aMenu[$mId][2] = "" Then
                    ; Should we show a popup ?
                    If $aMenu[$mId][3] <> "" Then
                        $Token = $aMenu[$mId][3]
                        $Token = StringReplace($Token,"<BR>",  @CR)
                        $Token = StringReplace($Token,"<HR>", $HRValue)
                        $Token = StringReplace($Token,"<TAB>", @TAB)
                        MsgBox(0+64,$Title,$Token)
                    Else
                        ; Execute nothing, as "Command=" is empty => exit from menu
                        ; MsgBox(0+48,$Title,"Exit from menu...")
                    EndIf
                Else
                    ; Execute the command...
                    $RetVal = Run($FullCommand)
                    If $DEBUG Then
                        If $RetVal = 0 and @error <> 0 Then MsgBox(0,"#Debug# - " & $Title & " - #Debug#","Error on execution of : " & $FullCommand)
                    EndIf
                EndIf

                ; Destroy menu & exit
                GUIDelete()
                Exit
            EndIf
        Next

     WEnd

EndFunc
; -----------------------------------8<-----------------------------------

post-64029-0-99172400-1301643707_thumb.j

Link to comment
Share on other sites

Edit on 05/04/2011 : I've improved the menu creation, time to load it & added a possibility to have a sub-branch.

Hello all,

Using since a long time AutoIt, here my first participation in this forum, hope this helps...

Here is a quick dynamic menu creation under right mouse click button, on any file/folder, using a simple ini file for list of "programs" to run.

Usage of myFloatingMenu is simple : once compiled (or not), it reads the ini file, and create a dynamic menu under user's cursor, each menu line corresponding to a [Menu_Line_XX] section from ini file.

Command line option :

  • myFloatingMenu.exe (call menu under user's cursor)
  • myFloatingMenu.exe <file name>|<foldername> (call menu, with parameter as current file/folder, usable via #CMDLINEx# parameters in ini file)
  • myFloatingMenu.exe /AddReg (Add current menu in registry, using ini RegKey=)
  • myFloatingMenu.exe /AddReg:"my_key" (Add current menu in registry)<BR><TAB>- myFloatingMenu.exe /DelReg (Delete current menu from registry)

The trick is, once added in registry (using /AddReg option on command line), this FloatingMenu is available for any right mouse click, on file/folder, to perform <your> specific action(s) described in the ini file :)

Enjoy...

---

Ini configuration is relatively easy : simply add in ini file list of [Menu_Line_XX] sections, that will cointain :

  • ( SubMenu = optional sub-branch from main menu)
  • Title = title of menu that will be created
  • Command = program to execute
  • Options = option on "command" command line

Here myFloatingMenu.ini file:

#~ -------------------------------------------------8<-------------------------------------------------
#~ [Default_Config]
#~ Debug    = [0|1]       (1 to activate "debug" mode, default value = 0)
#~ Revision = <any text>  (= your own revision of current ini file, for any TextBox ("Title=" + "Options=" only))
#~ MenuRegKey   = "<any text, may contain a &>"  (name of menu entry [in registry + for right click mouse button on any file/folder], default value is = "  + my&FloatingMenu...")
#~ Menu_Lines   = <a number>  (it's the number of the LAST menu section to take into account below ... ie, number of [Menu_Line_<1-999>] sections to read, to create the dynamic menu, any "gap" will be "jumped" (no menu row will be created)
#~ -------------------------------------------------8<-------------------------------------------------

[Default_Config]
Debug       = 0
Revision    = A.05
MenuRegKey  ="  + myFloatingMenu..."

Menu_Lines  = 100




#~ -------------------------------------------------8<-------------------------------------------------
#~ [Menu_Line_<1-999>]
#~ ( SubMenu    = OPTIONAL !!! <SubMenuName> : any [Menu_Line_xxx] section that will contain this "SubMenu =" paranmeter will be placed in same sub-branch of main menu. )
#~ Title    = <-> or <Menu Title> (can contain : #CMDLINE1#, #CMDLINE2# or #CMDLINE3#) or
#~                <Menu Title #Options# (and #Options# will be replaced by value of "Options=")> or
#~                <Menu Title without "Command=" and without "Option=" (= perform an EXIT)> or
#~                <Menu Title with "Options=" only = show a popup>,
#~                <if empty, no menu will be shown>
#~ Command  = <full command line to exe, WITHOUT quotes (")> or <leave empty> or
#~                <#COMSPECEXEC# : will directly execute the file/folder specified on "Title=" as it is (without any Option)>
#~ Options  = <possible command line option(s) for "Command=">...
#~                (can use too : #CMDLINE1#, #CMDLINE2# or #CMDLINE3# or \"#CMDLINE1#\", as parameters taken from script command line) or
#~                <Menu Title with "Options=" only, with "Options=" that could contain <BR><HR><TAB> = to show a text popup window with "Options" as text>  or <leave empty>
#~ -------------------------------------------------8<-------------------------------------------------


[Menu_Line_10]
Title   = #CMDLINE1#
Command = #COMSPECEXEC#

[Menu_Line_11]
Title   = notepad.exe
Command = #COMSPECEXEC#

[Menu_Line_12]
Title   = c:\WINDOWS\
Command = #COMSPECEXEC#

[Menu_Line_13]
Title   = MSDos box (Cmd.exe #Options#)
Command = cmd.exe
Options = /k echo. && cd && echo. && dir

[Menu_Line_14]
Title   = -



[Menu_Line_21]
Title   = - Dummy (error) exe program (no exec. will be performed)
Command = DummyProgramThatWillNotWork.exe
Options = \"#CMDLINE1#\"

[Menu_Line_22]
Title   = -



[Menu_Line_30]
Title   = Current selected file/folder is...
Options = The current selected "line" (file/folder) is =<BR>#CMDLINE1#


[Menu_Line_31]
Title   = Command line is : #CMDLINE1# #CMDLINE2# #CMDLINE3#
Options = Command line is (reverse order) : #CMDLINE3# #CMDLINE2# #CMDLINE1#

[Menu_Line_32]
Title   = -




[Menu_Line_40]
SubMenu = Explorer...
Title   = Explorer
Command = explorer.exe

[Menu_Line_41]
SubMenu = Explorer...
Title   =  + Start Explorer on \"c:\Documents and Settings\"
Command = c:\WINDOWS\explorer.exe
Options = \"c:\Documents and Settings"\

[Menu_Line_42]
SubMenu = Explorer...
Title   =  + Start Explorer on \"#CMDLINE1#\"
Command = c:\WINDOWS\explorer.exe
Options = \"#CMDLINE1#\"

[Menu_Line_43]
SubMenu = Explorer...
Title   = + Start Explorer on #Options#
Command = explorer
Options = \"#CMDLINE1#\"

[Menu_Line_44]
SubMenu = Explorer...
Title   =  + Start Explorer, taking first option on script command line (/e,/root,#CMDLINExx#)
Command = explorer.exe
Options = /e,/root,\"#CMDLINE1#\"

[Menu_Line_45]
Title   = -





[Menu_Line_50]
Title   = Start Internet Explorer (#Options#)
Command = c:\Program Files\Internet Explorer\iexplore.exe
Options = http://www.google.com


[Menu_Line_51]
Title   = -





[Menu_Line_60]
Title   = Start Notepad
Command = notepad


[Menu_Line_61]
Title   = Start Notepad (on file : #Options#)
Command = notepad
Options = #CMDLINE1#


#~ [Menu_Line_62]
#~ Title    = Excel (with doc. givent as 1st command line parameter)
#~ Command  = c:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE
#~ Options  = \"#CMDLINE1#\"


[Menu_Line_65]
Title   = -





[Menu_Line_70]
SubMenu = Open Folder...
Title   = Open folder via : Total Commander #Options#
Command = c:\Program Files\TOTALCMD.EXE
Options = /O /L=c:\WINDOWS

[Menu_Line_71]
SubMenu = Open Folder...
Title   = Open folder via : Total Commander #Options#
Command = c:\Program Files\TOTALCMD.EXE
Options = /O /R=c:\WINDOWS

[Menu_Line_72]
SubMenu = Open Folder...
Title   = Open folder via : Explorer #Options#
Command = explorer
Options = c:\WINDOWS


[Menu_Line_80]
Title   = -

[Menu_Line_81]
Title   = myFloatingMenu.exe : directly modify myFloatingMenu.ini config file...
Command = notepad
Options = myFloatingMenu.ini

[Menu_Line_82]
Title   = -



[Menu_Line_90]
SubMenu = Help/About...
Title   = Help... (myFloatingMenu.exe usage/add to registry/etc...)
Options = Syntaxe usage is<BR><TAB>- myFloatingMenu.exe    (call current menu)<BR><TAB>- myFloatingMenu.exe <file name>|<foldername>   (call menu, with parameter as current file/folder, usable via #CMDLINEx# parameters in ini file)<BR><TAB>- myFloatingMenu.exe /AddReg   (Add current menu in registry, using ini RegKey=)<BR><TAB>- myFloatingMenu.exe /AddReg:"my_key"   (Add current menu in registry)<BR><TAB>- myFloatingMenu.exe /DelReg   (Delete current menu from registry)

[Menu_Line_91]
SubMenu = Help/About...
Title   = -

[Menu_Line_92]
SubMenu = Help/About...
Title   = About...
Options = About example popup message box<BR>(c) 04/2011<BR><HR><BR>myFloatingMenu.exe is my Dynamic Menu "tool" (using a .ini file)<BR>for list of actions (programs) to perform on a selected file/folder.


[Menu_Line_92]
Title   = Nothing as [Menu_Line_91] is duplicated from previous one ! (only first [Menu_Line_xx] occurrence count)



[Menu_Line_100]
Title   = Exit (= dummy menu title option, for simple "exit")





[Menu_Line_100]
Title   = Nothing as already previously defined

[Menu_Line_200]
Title   = Nothing as out of "Menu_Lines" number...

Here the au3 script

; -----------------------------------8<-----------------------------------
; myFloatingMenu - Mjr. 04/04/2011 - Rev F.01
; -----------------------------------8<-----------------------------------
#include <array.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>


; -----------------------------------8<-----------------------------------
$Ini_File               = StringReplace(StringReplace(@ScriptFullPath,".au3",".ini"),".exe",".ini")
; -----------------------------------8<-----------------------------------
$DEBUG                  = IniRead($Ini_File, "Default_Config", "DEBUG",     0)
If $DEBUG = 1 Then
    $DEBUG = True
Else
    $DEBUG = False
EndIf
$Menu_Lines             = IniRead($Ini_File, "Default_Config", "Menu_Lines",0)
; -----------------------------------8<-----------------------------------
$HRValue                = "---"
; -----------------------------------8<-----------------------------------
$Title                  = StringReplace(StringReplace(@ScriptName,".au3",""),".exe","")
$Rev                    = IniRead($Ini_File, "Default_Config", "Revision",  0)
$Title                  = $Title & " - " & $Rev
; -----------------------------------8<-----------------------------------




; -----------------------------------8<-----------------------------------
; Registry FloatingMenu /RegAdd or /RegDel ?
If $CmdLine[0] = 1 Then
    If StringUpper(StringLeft($CmdLine[1],7)) = "/REGADD" or StringUpper(StringLeft($CmdLine[1],7)) = "/ADDREG" Then

        ; Get /RegAdd:"menu title to add in Registry"
        $RegKey = IniRead($Ini_File, "Default_Config", "MenuRegKey",    "  + my&FloatingMenu...")
        If $RegKey = "  + my&FloatingMenu..." Then
            $RegKey = StringMid($CmdLine[1],9)
            If StringLen($RegKey) = 0 Then $RegKey = "  + my&FloatingMenu..."
        EndIf

        ; Add current Script to Registry, on any File/Folder right mouse click menu
        $RetVal = RegWrite("HKEY_CLASSES_ROOT\*\shell\" & $RegKey & "\command","","REG_SZ",@ScriptFullPath & ' "%l"')
        $RetVal = $RetVal + RegWrite("HKEY_CLASSES_ROOT\Folder\shell\" & $RegKey & "\command","","REG_SZ",@ScriptFullPath & ' "%l"')
        If $RetVal = 2 Then
            MSgBox(0+64,$Title,"Successfully added key [" & $RegKey & "] in registry, for any file/folder mouse right button menu.")
        Else
            MSgBox(0+48,$Title,"Impossible to add in registry the key [" & $RegKey & "]")
        EndIf

        IniWrite($Ini_File, "Default_Config", "MenuRegKey", Chr(34) & $RegKey & Chr(34))

        Exit

    ElseIf StringUpper(StringLeft($CmdLine[1],7)) = "/REGDEL" or  StringUpper(StringLeft($CmdLine[1],7)) = "/DELREG" Then

        ; Get /RegDel:"menu title to delete from Registry"
        $RegKey = StringMid($CmdLine[1],9)
        If StringLen($RegKey) = 0 Then
            ; $RegKey = "  + myFloatingMenu..."
            $RegKey = IniRead($Ini_File, "Default_Config", "MenuRegKey",    "  + my&FloatingMenu...")
        EndIf

        ; Remove current Script from Registry, for any File/Folder right mouse click menu
        $RetVal = RegDelete("HKEY_CLASSES_ROOT\*\shell\" & $RegKey)
        $RetVal = $RetVal + RegDelete("HKEY_CLASSES_ROOT\Folder\shell\" & $RegKey)
        If $RetVal = 2 Then
            MSgBox(0+64,$Title,"Successfully deleted from registry key [" & $RegKey & "], for any file/folder mouse right button menu.")
        Else
            MSgBox(0+48,$Title,"Impossible to delete from registry the key [" & $RegKey & "]")
        EndIf
        Exit

    EndIf
EndIf
; -----------------------------------8<-----------------------------------




; -----------------------------------8<-----------------------------------
; Create a Menu Array + fill a header (not really necessary...) : Id, Menu title, Command
Local $aMenuRowUnseen = 0
Local $aMenuRow = 0
Local $aMenuCol = 6
Local $aMenu[$aMenuRow+1][$aMenuCol]
$aMenu[$aMenuRow][0] = "GUICtrlCreateMenuItem Handle"       ; $aMenu[x][0] : Will contain the "Handle" of the "GUICtrlCreateMenuItem" (see function GUIBuildAndShowMenu() )
$aMenu[$aMenuRow][1] = "Menu Title"                         ; $aMenu[x][1] : Will contain the "Title" from ini file   (see function BuildaMenuArray() )
$aMenu[$aMenuRow][2] = "Command"                            ; $aMenu[x][2] : Will contain the "Command" from ini file (see function BuildaMenuArray() )
$aMenu[$aMenuRow][3] = "Options"                            ; $aMenu[x][3] : Will contain the "Options" from ini file (see function BuildaMenuArray() )
$aMenu[$aMenuRow][4] = "SubMenu Handle"                     ; $aMenu[x][4] : Will contain the "Sub Menu branch" title level from ini file (see function BuildaMenuArray() )
$aMenu[$aMenuRow][5] = "SubMenu Title"                      ; $aMenu[x][5] : Will contain the "Sub Menu branch" Handle (see function GUIBuildAndShowMenu() )



; -----------------------------------8<-----------------------------------
; (only) Parse ini file to fill the Menu array with Title + Command + Options
BuildaMenuArray()


; -----------------------------------8<-----------------------------------
; Build & shouw the GUI menu (& fill the last empty column $aMenu[x][0] with the currently created MenuItem "handles")
GUIBuildAndShowMenu()

; -----------------------------------8<-----------------------------------
; Wait in loop user's "menu choice", and execute the selected command
GUIWaitUserMenuSelectionAndExecuteCommand()


Exit
; -----------------------------------8<-----------------------------------




; -----------------------------------8<-----------------------------------
; (only) Parse ini file to fill the Menu array with Title + Command + Options
Func BuildaMenuArray()
    For $mId = 1 to $Menu_Lines

        If IniRead($Ini_File, "Menu_Line_" & $mId, "Title",   "<No section Found !>") <> "<No section Found !>" Then

            $aMenuRow = $aMenuRow + 1
            ReDim $aMenu[$aMenuRow+1][$aMenuCol]

            $aMenu[$aMenuRow][0] = "<Empty at this step, will be = GUICtrlCreateMenuItem() during menu creation>"
            $aMenu[$aMenuRow][1] = StringReplace( IniRead($Ini_File, "Menu_Line_" & $mId, "Title",   "") ,'\"',Chr(34))
            $aMenu[$aMenuRow][2] = StringReplace( IniRead($Ini_File, "Menu_Line_" & $mId, "Command", "") ,'\"',"")
            $aMenu[$aMenuRow][3] = StringReplace( IniRead($Ini_File, "Menu_Line_" & $mId, "Options", "") ,'\"',Chr(34))

            $aMenu[$aMenuRow][4] = "<Empty at this step, will be = GUICtrlCreateContextMenu() during menu creation>"
            $aMenu[$aMenuRow][5] = IniRead($Ini_File, "Menu_Line_" & $mId, "SubMenu", "#MAIN#")
            If StringLen($aMenu[$aMenuRow][5]) = 0 Then $aMenu[$aMenuRow][5] = "#MAIN#"

            ; Below... replace in "Options", any #CMDLINEx# by the current script $CmdLine[X] value(s)
            For $cl = 1 to 3
                If $CmdLine[0] >= $cl Then
                    If StringInStr($aMenu[$aMenuRow][1],"#CMDLINE" & $cl & "#") <> 0 or StringInStr($aMenu[$aMenuRow][3],"#CMDLINE" & $cl & "#") <> 0 Then
                            $aMenu[$aMenuRow][1] = StringReplace($aMenu[$aMenuRow][1],"#CMDLINE" & $cl & "#",$CmdLine[$cl])
                            $aMenu[$aMenuRow][3] = StringReplace($aMenu[$aMenuRow][3],"#CMDLINE" & $cl & "#",$CmdLine[$cl])
                    EndIf
                Else
                    $aMenu[$aMenuRow][1] = StringReplace($aMenu[$aMenuRow][1],"#CMDLINE" & $cl & "#","")
                    $aMenu[$aMenuRow][3] = StringReplace($aMenu[$aMenuRow][3],"#CMDLINE" & $cl & "#","")
                EndIf
            Next

            ; Replace #Options# by "Options=" in Menu Title
            $aMenu[$aMenuRow][1] = StringReplace( $aMenu[$aMenuRow][1], "#Options#",$aMenu[$aMenuRow][3])

      Else
         $aMenuRowUnseen = $aMenuRowUnseen + 1
        EndIf

    Next

    ; -----------------------------------8<-----------------------------------
    If $DEBUG Then
        MsgBox(0+64,"#Debug# - " & $Title & " - #Debug#","Generic variables ..." & @CR & @CR & _
                  "Ini file :" & @CR & _
                  @TAB & "- declared 'Menu_Lines='" & @TAB & @TAB & $Menu_Lines & @CR & _
                        @TAB & "- 'unseen/dropped' sections count" & @TAB & $aMenuRowUnseen & @CR & _
                        @TAB & "- sections '[Menu_Line_xxx]' count" & @TAB & $aMenuRow & @CR & _
                        @CR & _
                        "Menu :" & @CR & _
                  @TAB & "- rows created/available" & @TAB & @TAB & $aMenuRow)
        _ArrayDisplay($aMenu,"#Debug# - " & $Title & " - " & "aMenu Array created - #Debug#")
    EndIf

EndFunc
; -----------------------------------8<-----------------------------------




; -----------------------------------8<-----------------------------------
; Build & shouw the GUI menu (& fill the last empty column $aMenu[x][0] with the currently created MenuItem "handles")
Func GUIBuildAndShowMenu()
    Local $hGui, $msg
    $pos = MouseGetPos()

    ; Create a GUI window.
    $hGui = GUICreate($Title, 0, 0,-1,-1,$WS_POPUP,BitOR($WS_EX_TOPMOST,$WS_EX_TOOLWINDOW))
    WinMove($Title, "", $pos[0]-3, $pos[1]-3)

    ; Create a dummy control and a contextmenu
    $MenuCtrl = GUICtrlCreateDummy()

    ; Creates a context menu for a control
    $aMenu[0][4]    = GUICtrlCreateContextMenu($MenuCtrl)

    ; Add lines in this '$MenuContext' menu & Fill the "last enpty column" $aMenu[x][0] with current GUICtrlCreateMenuItem "handle"
    ; If current menu name is <> from previous ($aMenu[$mId][5] => "SubMenu"), then, create a new "GUICtrlCreateMenu")
    For $mId = 1 to $aMenuRow
        If $aMenu[$mId][1] = "-" Then
            ; Create a SubMenu ?
            If $aMenu[$mId][5] <> "#MAIN#" and $aMenu[$mId][5] <> "" Then
                $aMenu[$mId][4] = $aMenu[$mId-1][4]
                $aMenu[$mId][0] = GUICtrlCreateMenuItem("", $aMenu[$mId][4])
            Else
                $aMenu[$mId][4] = $aMenu[0][4]
                $aMenu[$mId][0] = GUICtrlCreateMenuItem("", $aMenu[0][4])
            EndIf
        Else
            If StringLen($aMenu[$mId][1]) <> 0 Then
                ; Create a SubMenu ?
                If $aMenu[$mId][5] <> "#MAIN#" and $aMenu[$mId][5] <> "" Then
                    If $aMenu[$mId][5] <> $aMenu[$mId-1][5] Then
                        $aMenu[$mId][4] = GUICtrlCreateMenu($aMenu[$mId][5],$aMenu[0][4])
                    Else
                        $aMenu[$mId][4] = $aMenu[$mId-1][4]
                    EndIf
                    $aMenu[$mId][0] = GUICtrlCreateMenuItem($aMenu[$mId][1], $aMenu[$mId][4])
                Else
                    $aMenu[$mId][4] = $aMenu[0][4]
                    $aMenu[$mId][0] = GUICtrlCreateMenuItem($aMenu[$mId][1], $aMenu[0][4])
                EndIf
            Else
                $aMenu[$mId][0] = "<No menu there !>"
            EndIf
        EndIf
    Next

    ; Changes the state of a GUI window (default = Hide)
    GUISetState()

    If $DEBUG Then _ArrayDisplay($aMenu,"#Debug# - " & $Title & " - " & "aMenu Array now filled with GUICtrlCreateMenuItem() 'handles' - #Debug#")

    ; Show the menu
    GUIShowMenu($hGui, $msg, $aMenu[0][4])

EndFunc
; -----------------------------------8<-----------------------------------
; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func GUIShowMenu($hWnd, $CtrlID, $nContextID)
    Local $arPos, $x, $y
    Local $hMenu = GUICtrlGetHandle($nContextID)
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
    $x = $arPos[0]
    $y = $arPos[1] + $arPos[3]
    GUIConvertClientToScreen($hWnd, $x, $y)
    GUIShowAndTrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc
; -----------------------------------8<-----------------------------------
; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func GUIConvertClientToScreen($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
; -----------------------------------8<-----------------------------------
; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd)
Func GUIShowAndTrackPopupMenu($hWnd, $hMenu, $x, $y)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc
; -----------------------------------8<-----------------------------------





; -----------------------------------8<-----------------------------------
; Wait in loop user's "menu choice", and execute the selected command
Func GUIWaitUserMenuSelectionAndExecuteCommand()

    ; Loop (parse) "forever" menu until option choosed or [Esc]
    While True

        ; Wait for menu choice
        $msg = GUIGetMsg()

        ; Check for Esc key press
        If $msg = $GUI_EVENT_CLOSE or $msg = 0 Then
            ; Destroy menu & exit
            GUIDelete()
            Exit
        EndIf

        ; Check to execute command... by comparing each $msg to id in aMenu[x][0]
        For $mId = 1 to $aMenuRow

            ; Found a MenuItem "Handle" matching user's choice... build possible command to execute...
            If $msg = $aMenu[$mId][0] Then

                ; Execute selected menu command...
                $FullCommand = Chr(34) & $aMenu[$mId][2] & Chr(34) & " " & $aMenu[$mId][3]
                If $DEBUG Then MsgBox(0+64,"#Debug# - " & $Title & " - #Debug#","Selected Menu Item :" & @CR & "- Execute menu line #" & $mId & " (Row)" & @CR & "- Title : " & $aMenu[$mId][1] & @CR & "- Command : " & $aMenu[$mId][2] & @CR & "- Option : " & $aMenu[$mId][3] & @CR & "- (Possible) Full executable Command (depending on Command= & Options=) : " & @CR & @TAB & $FullCommand)

                ; If $aMenu[x][2] is empty ("Command="), then, try to show a popup (if $aMenu[$mId][3] ("Options=") is NOT empty) -or- directly exit menu
                If $aMenu[$mId][2] = "" Then
                    ; Should we show a popup ?
                    If $aMenu[$mId][3] <> "" Then
                        $Token = $aMenu[$mId][3]
                        $Token = StringReplace($Token,"<BR>",  @CR)
                        $Token = StringReplace($Token,"<HR>", $HRValue)
                        $Token = StringReplace($Token,"<TAB>", @TAB)
                        MsgBox(0+64,$Title,$Token)
                    Else
                        ; Execute nothing, as "Command=" is empty => exit from menu
                        ; MsgBox(0+48,$Title,"Exit from menu...")
                    EndIf
                Else
                    ; Execute the command...
                    If $aMenu[$mId][2] = "#COMSPECEXEC#" Then
                        ; Execute directly file/folder on commandline
;~                      If FileExists($aMenu[$mId][1]) Then
                            $RetVal = ShellExecute($aMenu[$mId][1])
;~                      Else
;~                          MsgBox(0+16,$Title,"File/Folder [ " & $aMenu[$mId][1] & " ] does not exists." & @CR & "Abort.")
;~                      EndIf
                    Else
                        ; Execute the FullCommand (Command + Options)
                        $RetVal = Run($FullCommand)
                    EndIf
                    If $DEBUG Then
                        If $RetVal = 0 and @error <> 0 Then MsgBox(0,"#Debug# - " & $Title & " - #Debug#","Error on execution of : " & $FullCommand)
                    EndIf
                EndIf

                ; Destroy menu & exit
                GUIDelete()
                Exit
            EndIf
        Next

     WEnd

EndFunc
; -----------------------------------8<-----------------------------------

Link to comment
Share on other sites

  • 5 weeks later...

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...