I was wondering if you could use this to mimick something from
Quicksilver: Application Menus, you can watch a video here:
http://www.themerlin... ... tion-menusBasically:
- you press a hotkey
- you get a list of the entire menu from the current application
- you can do a incremental search (like iswitch)
- execute selected menu
Edit: to answer my own question, yes it is possible, at least
with some applications. I've tested the script briefly below with
Total Commander and Notepad++ and it seems to work.
- Run the script
- Press capslock
- Type to search menu item
- Hit enter
- and if all goes well it the chosen menu item should be executed
(Doesn't seem to work with UltraEdit, MS Word...)
Warning: The code below has been merged from two scripts just to
make it work, so it can be improved a lot I think. Would be nice if
MS Word and other applications could be supported...
; ---------------------------------------------------------------------
; merged two scripts:
; 1)
; Name: Incremental Listbox
; http://www.autohotkey.com/forum/viewtopic.php?t=2534
; 2)
; name: extracting menus
; http://www.autohotkey.com/forum/viewtopic.php?t=8492
; ---------------------------------------------------------------------
; -- Configuration: ---------------------------------------------------
; ---------------------------------------------------------------------
;Your favourite hotkey:
CapsLock:: ;Hotkey CapsLock to start
ControlGetFocus, control, A
;The name of the textfile containing the contents of the listbox:
GetMenuListTexts()
; ---------------------------------------------------------------------
; -- Autoexecute ------------------------------------------------------
; ---------------------------------------------------------------------
Gui, Add, ListBox, vChoice gListBoxClick w400 h250 vscroll
Gui, Add, Text, x10 y264 w50 h20, Search`:
Gui, Add, Edit, x66 y261 w343 h20
Gosub RefreshListBox
search =
;The input-command in this loop processes keys pressed by the user
;or send by the "send"-command
Loop
{
Input, input, L1, {enter}{esc}{backspace}{up}{down}{pgup}{pgdn}{tab}{left}{right}
if ErrorLevel = EndKey:escape
{
Gui, cancel
Gosub GuiClose
}
if ErrorLevel = EndKey:enter
{
GoSub, WordRetrieve
continue
}
if ErrorLevel = EndKey:backspace
{
GoSub, DeleteSearchChar
continue
}
if ErrorLevel = EndKey:up
{
Send, {up}
continue
}
if ErrorLevel = EndKey:down
{
Send, {down}
continue
}
if ErrorLevel = EndKey:pgup
{
Send, {pgup}
continue
}
if ErrorLevel = EndKey:pgdn
{
Send, {pgdn}
continue
}
search = %search%%input% ;Assembles the search string
GuiControl,, Edit1, %search% ;Displays the search string in the edit control
StringLen,SearchLength,Search
Gosub RefreshListBox
continue
}
return
; ---------------------------------------------------------------------
; -- Subroutines ------------------------------------------------------
; ---------------------------------------------------------------------
;Assigns the chosen item to the variable "Choice".
WordRetrieve:
Gui, submit, noHide
GuiControlGet, Choice ; Retrieve the ListBox's current selection.
Gui, Destroy
Loop, parse, MenuListTexts, |
{
If (Choice = A_LoopField)
{
SendMenuItem:=command%A_Index%-1
ControlGetFocus, control, HWND
PostMessage, 0x111, %SendMenuItem%, %Control%,,A
;MsgBox %Choice%, %SendMenuItem%
ExitApp
}
continue
}
Return
; ---------------------------------------------------------------------
;Exits the script on closing the GUI
GuiClose:
GuiEscape:
ExitApp
; ---------------------------------------------------------------------
;Refreshes the listbox according to the search criteria:
RefreshListBox:
Wordlist=
Loop, parse, MenuListTexts, |
{
IfInString, A_LoopField,%Search%
Wordlist=%Wordlist%|%A_LoopField%
Else
continue
}
Gui, Show,
GuiControl,, ListBox1, %wordlist%
GuiControl, Choose, ListBox1, 1
return
;-------------------------------------------------------------------------
;Delete the last character and update Listbox:
DeleteSearchChar:
if search =
return
StringTrimRight, search, search, 1
GuiControl,, Edit1, %search%
GoSub, RefreshListBox
return
;-------------------------------------------------------------------------
; Handle mouse click events on the list box:
ListBoxClick:
if A_GuiControlEvent = DoubleClick
send, {enter}
return
; --------------
GetMenuListTexts()
{
global
WinGet hWnd, ID, A
hMenu := DllCall("GetMenu", "UInt", hWnd)
wholeMenu =
GetMenu(hMenu, wholeMenu)
Clipboard = %wholeMenu%
StringReplace, clipboard, clipboard, `&, , All
StringReplace, clipboard, clipboard, %A_Tab%, %A_Space%-%A_Space%, All
StringReplace, clipboard, clipboard, +, -, All
;MsgBox %clipboard%
test=0
command=0
MenuText=0
Loop, parse, clipboard, `n
{
StringLeft, command%A_Index%,A_LoopField, 5
StringTrimLeft, MenuText%A_Index%, A_LoopField, 6
tmp:=MenuText%A_Index%
MenuListTexts=%MenuListTexts%|%tmp%
}
}
GetMenu(_hMenu, ByRef @wholeMenu, _menuLevel=0)
{
local menuItemCount, indent, nPos, length, lpString, id, hSubMenu
menuItemCount := DllCall("GetMenuItemCount", "UInt", _hMenu)
indent =
Loop %menuItemCount%
{
nPos := A_Index - 1
length := DllCall("GetMenuString"
, "UInt", _hMenu
, "UInt", nPos
, "UInt", 0 ; NULL
, "Int", 0 ; Get length
, "UInt", 0x0400) ; MF_BYPOSITION
VarSetCapacity(lpString, length + 1) ; I don't check the result...
length := DllCall("GetMenuString"
, "UInt", _hMenu
, "UInt", nPos
, "Str", lpString
, "Int", length + 1
, "UInt", 0x0400)
id := DllCall("GetMenuItemID", "UInt", _hMenu, "Int", nPos)
If length > 0 ; 0 if not of MFT_STRING type or error
{
If id < 0
{
If _menuLevel = 0
id = _____
Else
id = ––––0
}
Else
{
id = 00000%id%
StringRight id, id, 5
}
@wholeMenu = %@wholeMenu%%id%|%lpString%`n
}
hSubMenu := DllCall("GetSubMenu", "UInt", _hMenu, "Int", nPos)
If hSubMenu != 0
{
GetMenu(hSubMenu, @wholeMenu, _menuLevel + 1)
}
}