Leef_me wrote:
...in an external program?
I modified
Micha's
Get Info from Context Menu to do the job, but as Micha stated it works on...
Quote:
standard windows context menus only!!!
Code:
;constants
MFS_HILITE = 0x80
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#Persistent
Return
#IfWinExist ahk_class #32768
LButton::
Enter::
NumPadEnter::
WinGet, hwnd, ID, A
WinGet, hMenu, ID, ahk_class #32768
;Get count of menu items
ContextMenCnt := GetContextMenuCount(hMenu)
If ContextMenCnt < 1
{
Tooltip
Return
}
item =
Loop %ContextMenCnt%
{
IsEnabled := GetContextMenuState(hMenu, A_Index-1)
If (IsEnabled & MFS_HILITE)
item := A_Index
}
If item
Tooltip, % GetContextMenuText(hMenu, item - 1)
Else
ToolTip
If A_ThisHotkey = LButton
Click Down
Else
ControlSend, , {%A_ThisHotkey%}, ahk_id %hwnd%
Return
~LButton Up:: Return
/***************************************************************
* returns the count of menu items
***************************************************************
*/
GetContextMenuCount(hMenu)
{
WinGetClass, WindowClass, ahk_id %hMenu%
;All popups should have the window class #32768
if WindowClass <> #32768
{
return 0
}
;Retrieve menu handle from window
SendMessage, 0x01E1, , , , ahk_id %hMenu%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
menuitemcount:=DllCall("GetMenuItemCount",UInt,hMenu)
Return, menuitemcount
}
/***************************************************************
* returns the state of a menu entry
***************************************************************
*/
GetContextMenuState(hMenu, Position)
{
WinGetClass, WindowClass, ahk_id %hMenu%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hMenu%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;We need to allocate a struct
VarSetCapacity(MenuItemInfo, 60, 0)
;Set Size of Struct to the first member
NumPut(48, MenuItemInfo, 0, 4)
;Get only Flags from dllcall GetMenuItemInfo MIIM_TYPE = 1
NumPut(1, MenuItemInfo, 4, 4)
;GetMenuItemInfo: Handle to Menu, Index of Position, 0=Menu identifier / 1=Index
InfoRes := DllCall("user32.dll\GetMenuItemInfo",UInt,hMenu, Uint, Position, uint, 1, "int", &MenuItemInfo)
InfoResError := errorlevel
LastErrorRes := DllCall("GetLastError")
if InfoResError <> 0
return -1
if LastErrorRes != 0
return -1
;Get Flag from struct
; GetMenuItemInfoRes := ExtractInteger(MenuItemInfo, 12, false, 4)
; GetMenuItemInfoRes0 := ExtractInteger(MenuItemInfo, 12, false, 4)
GetMenuItemInfoRes := NumGet(MenuItemInfo, 12)
GetMenuItemInfoRes0a := NumGet(MenuItemInfo, 12)
/*
IsEnabled = 1
if GetMenuItemInfoRes > 0
IsEnabled = 0
return IsEnabled
*/
return GetMenuItemInfoRes
}
/***************************************************************
* returns the text of a menu entry (standard windows context menus only!!!)
***************************************************************
*/
GetContextMenuText(hMenu, Position)
{
Global GetMenuItemInfoRes0
Global GetMenuItemInfoRes0a
Global GetMenuItemInfoRes1
Global GetMenuItemInfoRes1a
WinGetClass, WindowClass, ahk_id %hMenu%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hMenu%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;We need to allocate a struct
VarSetCapacity(MenuItemInfo, 200, 0)
;Set Size of Struct (48) to the first member
NumPut(48, MenuItemInfo, 0, 4)
;Retrieve string MIIM_STRING = 0x40 = 64 (/ MIIM_TYPE = 0x10 = 16)
NumPut(64, MenuItemInfo, 4, 4)
;Set type - Get only size of string we need to allocate
;NumPut(0, MenuItemInfo, 8, 4)
;GetMenuItemInfo: Handle to Menu, Index of Position, 0=Menu identifier / 1=Index
InfoRes := DllCall("user32.dll\GetMenuItemInfo",UInt,hMenu, Uint, Position, uint, 1, "int", &MenuItemInfo)
if InfoRes = 0
return -1
InfoResError := errorlevel
LastErrorRes := DllCall("GetLastError")
if InfoResError <> 0
return -1
if LastErrorRes <> 0
return -1
;Get size of string from struct
; GetMenuItemInfoRes := ExtractInteger(MenuItemInfo, 40, false, 4)
; GetMenuItemInfoRes1 := ExtractInteger(MenuItemInfo, 40, false, 4)
GetMenuItemInfoRes := NumGet(MenuItemInfo, 40)
GetMenuItemInfoRes1a := NumGet(MenuItemInfo, 40)
;If menu is empty return
If GetMenuItemInfoRes = 0
return "{Empty String}"
;+1 should be enough, we'll use 2
GetMenuItemInfoRes += 2
;Set capacity of string that will be filled by windows
VarSetCapacity(PopupText, GetMenuItemInfoRes, 0)
;Set Size plus 0 terminator + security ;-)
NumPut(GetMenuItemInfoRes, MenuItemInfo, 40, 4)
NumPut(&PopupText, MenuItemInfo, 36, 4)
InfoRes := DllCall("user32.dll\GetMenuItemInfo",UInt,hMenu, Uint, Position, uint, 1, "int", &MenuItemInfo)
if InfoRes = 0
return -1
InfoResError := errorlevel
LastErrorRes := DllCall("GetLastError")
if InfoResError <> 0
return -1
if LastErrorRes <> 0
return -1
return PopupText
}
PrintScreen::reload
Also, it doesn't work on Explorer's / IE's favorites (it's really not a menu), and some submenus (like Explorer's
File -> Send) show "{Empty String}".
It's not perfect: it works if the item is selected by a mouse or Enter key, but not when it's selected by a key, which is underlined in the menu (preceded by an ampersand in the tooltip).