 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
txquestor's Guest
|
Posted: Sat Sep 12, 2009 3:55 am Post subject: Need Help to add MenuitemID to dynamic menuitem tooltip |
|
|
This script already works to display a menuitem's Name & Hotkey or menuitem ID.
However, I need help to combine the two code snippets to display
the menuitem ID, Name & Hotkey at the same time.
Dynamically update a tooltip while scrolling thru each menuitem in any menu type.
I call it a MenuSpy.
I've been experimenting with Micha's Sean's & Majkinetor's: Menu scripts.
Specifically the GetContextMenu.... & GetMenu ... Functions.
I've been trying to figure out how to display the contents of each menuitem in any type of menu:
standard, context, popup,tray & ahk menus ONLY in a tooltip as I mouseover each menuitem.
I finally got it working. It displays and updates the Menuitem Name & Hotkey dynamically
in a tooltip as user moves from menuitem to menuitem.
Thanks for the Great menu work! Micha, Sean & Majkinetor:
Use the latest version of Autohotkey 1.0.48.02
How to use this script.
1. Open an application with standards menus. Example: Notepad
2. Run this script
3. Select a Menu, try the EDIT menu.
4. Start moving slowly thru each menuitem
5. The Tooltip appears in the upper left corner of the desktop window
6. The tooltip dynamically updates with the menuitem's Name & Hotkey
As I mentioned above. This works on any type of menu;
standard, context, popup,tray & ahk menus
Even IExplorer, Explorer, and many others.
If it doesn't work on a menu. Then it's NOT a STANDARD Menu!!
You'll need to customize it to suit your needs.
Here's the code.
; MenuSpy
; Select Menuitem and it displays Tooltip for any Menu/Menuitem Dynamically
; This script uses part or all of these Menu Scripts
; Micha: GetContext Menu - http://www.autohotkey.com/forum/topic21451.html
; Sean: GetInfo fromContext Menu - http://www.autohotkey.com/forum/viewtopic.php?p=137692.html
; Majkinetor: MMenu - http://www.autohotkey.com/forum/topic17674.html
| Code: |
; MenuSpy
; It dynamically displays the menuitem Name & Hotkey in a tooltip as user moves thru each menuitem.
; To view the menuitem ID ONLY - Uncomment the code snippet below & comment out label code.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#Persistent
SetTimer, Demo, 500
return
Demo:
;constants
MFS_HILITE = 0x80
WinGet hWnd, ID, A
hMenu := DllCall("GetMenu", "UInt", hWnd) ; VERIFIED for TextText
MouseGetPos, MouseScreenX, MouseScreenY, MouseWindowUID, MouseControlID
WinGet,ControlHwnd, ID,ahk_id %MouseWindowUID%
;Get count of menu items
ContextMenCnt := GetContextMenuCount(ControlHwnd)
if ContextMenCnt < 1
{
Tooltip,
}
;Read info for each menu item on Highlight
loop, %ContextMenCnt%
{
IsEnabled := GetContextMenuState(ControlHwnd, a_index-1)
; UnComment for use with MenuitemID
;SendMessage, 0x1E1, 0,0,, ahk_class #32768 ; VERIFIED for MenuitemID, FAILED BREAKS Menuitem Name & Hotkey portion
;hMenu := ErrorLevel
{
TextText =
if (IsEnabled & MFS_HILITE)
; menu item identifier of a menu item located at the specified position in a menu using the GetMenuItemID function
;MenuitemID := DllCall( "GetMenuItemID", UInt, hMenu, Int, a_index-1 ) ; VERIFIED - UnComment when used with hMenu in "hMenu=errorlevel" above
StrSize := GetContextMenuText(ControlHwnd, a_index-1)
TextText = %TextText%%a_index%:%StrSize%`n ; VERIFIED w/o MenuitemID - Comment Out for MenuitemID
;Msgbox TextText=%TextText% Index=%a_index% StrSize=%StrSize%`n
StringTrimLeft, TextText, TextText, 2
StringReplace, TextText, TextText, `:, , All
TextText = %TextText% ; VERIFIED w/o MenuitemID - Comment Out for MenuitemID
;TextText = %TextText%ID=%MenuitemID% ; ****VERIFIED when used with DllCall( "GetMenuItemID" ONLY ***
}
}
CoordMode, Tooltip, Screen
Tooltip, %TextText%, 0, 0
return
ESC::ExitApp
/***************************************************************
* Micha - Returns the TEXT of a menu entry (standard, context, popup & ahk menus only!!!)
***************************************************************
*/
GetContextMenuText(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768 ; Get Class of Menu/Menuitem
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;Allocate a struct for MenuItemInfo. It contains all the data of a Menu/Menuitem
VarSetCapacity(MenuItemInfo, 200, 0)
;Set Size of Struct [48] to the first member
InsertInteger(48, MenuItemInfo, 0, 4)
;Retrieve string MIIM_STRING = 0x40 = 64 (/ MIIM_TYPE = 0x10 = 16)
InsertInteger(64, 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)
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)
;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 ;-)
InsertInteger(GetMenuItemInfoRes, MenuItemInfo, 40, 4)
InsertInteger(&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
}
/***************************************************************
* Micha - returns the count of menu items
***************************************************************
*/
GetContextMenuCount(hWnd)
{
WinGetClass, WindowClass, ahk_id %hWnd%
;All popups should have the window class #32768
if WindowClass <> #32768
{
return 0
}
;Retrieve menu handle from window
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
menuitemcount:=DllCall("GetMenuItemCount",UInt,hMenu)
Return, menuitemcount
}
/***************************************************************
* Micha - returns the state of a menu entry
***************************************************************
*/
GetContextMenuState(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;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
InsertInteger(48, MenuItemInfo, 0, 4)
;Get only Flags from dllcall GetMenuItemInfo MIIM_TYPE = 1
InsertInteger(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)
return GetMenuItemInfoRes
}
GetMenu(hMenu)
{
Loop, % DllCall("GetMenuItemCount", "Uint", hMenu)
{
idx := A_Index - 1
idn := DllCall("GetMenuItemID", "Uint", hMenu, "int", idx)
nSize++ := DllCall("GetMenuString", "Uint", hMenu, "int", idx, "Uint", 0, "int", 0, "Uint", 0x400)
VarSetCapacity(sString, nSize)
DllCall("GetMenuString", "Uint", hMenu, "int", idx, "str", sString, "int", nSize, "Uint", 0x400) ;MF_BYPOSITION
If !sString
sString := "---------------------------------------"
sContents .= idx . " : " . idn . A_Tab . A_Tab . sString . "`n"
;msgbox idn=%idn%
If (idn = -1) && (hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", idx))
sContents .= GetMenu(hSubMenu)
}
Return sContents
}
;/*
; *********************************
; Original versions of ExtractInteger and InsertInteger provided by Chris
; - from the AutoHotkey help file - Version 1.0.37.04
; *********************************
; *********************************
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
SourceAddress := &pSource + pOffset ; Get address and apply the caller's offset.
result := 0 ; Init prior to accumulation in the loop.
Loop %pSize% ; For each byte in the integer:
{
result := result | (*SourceAddress << 8 * (A_Index - 1)) ; Build the integer from its bytes.
SourceAddress += 1 ; Move on to the next byte.
}
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset
; are altered in it. The caller must ensure that pDest has sufficient capacity.
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index - 1, UInt, 1 ; Write one byte.
, UChar, (pInteger & mask) >> 8 * (A_Index - 1)) ; This line is auto-merged with above at load-time.
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
|
|
|
| Back to top |
|
 |
HotKeyIt
Joined: 18 Jun 2008 Posts: 1994 Location: GERMANY
|
Posted: Sat Sep 12, 2009 10:47 am Post subject: |
|
|
Like this  | Code: |
; MenuSpy
; It dynamically displays the menuitem Name & Hotkey in a tooltip as user moves thru each menuitem.
; To view the menuitem ID ONLY - Uncomment the code snippet below & comment out label code.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#Persistent
SetTimer, Demo, 500
return
Demo:
;constants
MFS_HILITE = 0x80
WinGet hWnd, ID, A
hMenu := DllCall("GetMenu", "UInt", hWnd) ; VERIFIED for TextText
MouseGetPos, MouseScreenX, MouseScreenY, MouseWindowUID, MouseControlID
WinGet,ControlHwnd, ID,ahk_id %MouseWindowUID%
;Get count of menu items
ContextMenCnt := GetContextMenuCount(ControlHwnd)
if ContextMenCnt < 1
{
Tooltip,
}
;Read info for each menu item on Highlight
loop, %ContextMenCnt%
{
IsEnabled := GetContextMenuState(ControlHwnd, a_index-1)
; UnComment for use with MenuitemID
;SendMessage, 0x1E1, 0,0,, ahk_class #32768 ; VERIFIED for MenuitemID, FAILED BREAKS Menuitem Name & Hotkey portion
;hMenu := ErrorLevel
{
TextText =
if (IsEnabled & MFS_HILITE)
; menu item identifier of a menu item located at the specified position in a menu using the GetMenuItemID function
;MenuitemID := DllCall( "GetMenuItemID", UInt, hMenu, Int, a_index-1 ) ; VERIFIED - UnComment when used with hMenu in "hMenu=errorlevel" above
StrSize := GetContextMenuText(ControlHwnd, a_index-1),index:=A_Index-1
TextText = %TextText%%a_index%:%StrSize%`n ; VERIFIED w/o MenuitemID - Comment Out for MenuitemID
;Msgbox TextText=%TextText% Index=%a_index% StrSize=%StrSize%`n
StringTrimLeft, TextText, TextText, 2
StringReplace, TextText, TextText, `:, , All
TextText = %TextText% ; VERIFIED w/o MenuitemID - Comment Out for MenuitemID
;TextText = %TextText%ID=%MenuitemID% ; ****VERIFIED when used with DllCall( "GetMenuItemID" ONLY ***
}
}
CoordMode, Tooltip, Screen
Tooltip, % TextText ? index " : " . TextText : "", 0, 0
return
ESC::ExitApp
/***************************************************************
* Micha - Returns the TEXT of a menu entry (standard, context, popup & ahk menus only!!!)
***************************************************************
*/
GetContextMenuText(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768 ; Get Class of Menu/Menuitem
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;Allocate a struct for MenuItemInfo. It contains all the data of a Menu/Menuitem
VarSetCapacity(MenuItemInfo, 200, 0)
;Set Size of Struct [48] to the first member
InsertInteger(48, MenuItemInfo, 0, 4)
;Retrieve string MIIM_STRING = 0x40 = 64 (/ MIIM_TYPE = 0x10 = 16)
InsertInteger(64, 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)
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)
;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 ;-)
InsertInteger(GetMenuItemInfoRes, MenuItemInfo, 40, 4)
InsertInteger(&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
}
/***************************************************************
* Micha - returns the count of menu items
***************************************************************
*/
GetContextMenuCount(hWnd)
{
WinGetClass, WindowClass, ahk_id %hWnd%
;All popups should have the window class #32768
if WindowClass <> #32768
{
return 0
}
;Retrieve menu handle from window
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
menuitemcount:=DllCall("GetMenuItemCount",UInt,hMenu)
Return, menuitemcount
}
/***************************************************************
* Micha - returns the state of a menu entry
***************************************************************
*/
GetContextMenuState(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;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
InsertInteger(48, MenuItemInfo, 0, 4)
;Get only Flags from dllcall GetMenuItemInfo MIIM_TYPE = 1
InsertInteger(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)
return GetMenuItemInfoRes
}
GetMenu(hMenu)
{
Loop, % DllCall("GetMenuItemCount", "Uint", hMenu)
{
idx := A_Index - 1
idn := DllCall("GetMenuItemID", "Uint", hMenu, "int", idx)
nSize++ := DllCall("GetMenuString", "Uint", hMenu, "int", idx, "Uint", 0, "int", 0, "Uint", 0x400)
VarSetCapacity(sString, nSize)
DllCall("GetMenuString", "Uint", hMenu, "int", idx, "str", sString, "int", nSize, "Uint", 0x400) ;MF_BYPOSITION
If !sString
sString := "---------------------------------------"
sContents .= idx . " : " . idn . A_Tab . A_Tab . sString . "`n"
;msgbox idn=%idn%
If (idn = -1) && (hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", idx))
sContents .= GetMenu(hSubMenu)
}
Return sContents
}
;/*
; *********************************
; Original versions of ExtractInteger and InsertInteger provided by Chris
; - from the AutoHotkey help file - Version 1.0.37.04
; *********************************
; *********************************
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
SourceAddress := &pSource + pOffset ; Get address and apply the caller's offset.
result := 0 ; Init prior to accumulation in the loop.
Loop %pSize% ; For each byte in the integer:
{
result := result | (*SourceAddress << 8 * (A_Index - 1)) ; Build the integer from its bytes.
SourceAddress += 1 ; Move on to the next byte.
}
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset
; are altered in it. The caller must ensure that pDest has sufficient capacity.
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index - 1, UInt, 1 ; Write one byte.
, UChar, (pInteger & mask) >> 8 * (A_Index - 1)) ; This line is auto-merged with above at load-time.
mask := mask << 8 ; Set it up for isolation of the next byte.
}
} |
_________________ AutoHotFile - ToolTip(n,text,title,options) |
|
| Back to top |
|
 |
txquestor
Joined: 22 Aug 2009 Posts: 294
|
Posted: Sat Sep 12, 2009 5:05 pm Post subject: |
|
|
Thanks for the quick response HotkeyIt!
Although your syntax is correct.. I'm trying to put the value of "GetMenuItemID" where
you are inserting a "Index" value.
See MSDN http://msdn.microsoft.com/en-us/library/ms647979(VS.85).aspx
The following code does not work but it gives an example of what I'm trying to do.
Replace:
| Code: | ;StrSize := GetContextMenuText(ControlHwnd, a_index-1)
|
New:
| Code: | | StrSize := GetContextMenuText(ControlHwnd, a_index-1),MenuitemID := DllCall( "GetMenuItemID", UInt, hMenu, Int, a_index-1 ) |
Replace:
| Code: | | Tooltip, %TextText%, 0, 0 |
New:
| Code: | Tooltip, % TextText ? MenuitemID " : " . TextText : "", 0, 0
|
If you want to see what value I'm trying to insert into the Tooltip
Do the following without making the changes above. Instead do the following.
; UnComment these lines:
| Code: | SendMessage, 0x1E1, 0,0,, ahk_class #32768 ; VERIFIED for MenuitemID, FAILED BREAKS Menuitem Name & Hotkey portion
;hMenu := ErrorLevel |
| Code: | | TextText = %TextText%ID=%MenuitemID% ; ****VERIFIED when used with DllCall( "GetMenuItemID" ONLY *** |
Comment Out these lines:
| Code: | | TextText = %TextText%%a_index%:%StrSize%`n ; VERIFIED w/o MenuitemID |
| Code: | | TextText = %TextText% ; VERIFIED w/o MenuitemID |
And then start Notepad & run the script. You'll see the "GetMenuItemID" value (range 1-65999) for each menuitem in the Tooltip
as you slowly move the thru each menuitem under a Menu, eg. Edit in Notepad is a good example.
Thanks again for your help! _________________
"Man's quest for knowledge is an expanding series whose limit is infinity" |
|
| Back to top |
|
 |
HotKeyIt
Joined: 18 Jun 2008 Posts: 1994 Location: GERMANY
|
Posted: Sat Sep 12, 2009 7:14 pm Post subject: |
|
|
How about that  | Code: |
; MenuSpy
; It dynamically displays the menuitem Name & Hotkey in a tooltip as user moves thru each menuitem.
; To view the menuitem ID ONLY - Uncomment the code snippet below & comment out label code.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#Persistent
SetTimer, Demo, 500
return
Demo:
;constants
MFS_HILITE = 0x80
WinGet hWnd, ID, A
hMenu := DllCall("GetMenu", "UInt", hWnd) ; VERIFIED for TextText
MouseGetPos, MouseScreenX, MouseScreenY, MouseWindowUID, MouseControlID
WinGet,ControlHwnd, ID,ahk_id %MouseWindowUID%
;Get count of menu items
ContextMenCnt := GetContextMenuCount(ControlHwnd)
if ContextMenCnt < 1
{
Tooltip,
}
;Read info for each menu item on Highlight
loop, %ContextMenCnt%
{
IsEnabled := GetContextMenuState(ControlHwnd, a_index-1)
; UnComment for use with MenuitemID
;SendMessage, 0x1E1, 0,0,, ahk_class #32768 ; VERIFIED for MenuitemID, FAILED BREAKS Menuitem Name & Hotkey portion
;hMenu := ErrorLevel
{
TextText =
if (IsEnabled & MFS_HILITE){
; menu item identifier of a menu item located at the specified position in a menu using the GetMenuItemID function
;MenuitemID := DllCall( "GetMenuItemID", UInt, hMenu, Int, a_index-1 ) ; VERIFIED - UnComment when used with hMenu in "hMenu=errorlevel" above
StrSize := GetContextMenuText(ControlHwnd, a_index-1)
SendMessage, 0x01E1, , , , ahk_id %ControlHwnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
MenuitemID := DllCall( "GetMenuItemID", "UInt", ErrorLevel, "Int", a_index-1 )
}
TextText = %TextText%%a_index%:%StrSize%`n ; VERIFIED w/o MenuitemID - Comment Out for MenuitemID
;Msgbox TextText=%TextText% Index=%a_index% StrSize=%StrSize%`n
StringTrimLeft, TextText, TextText, 2
StringReplace, TextText, TextText, `:, , All
TextText = %TextText% ; VERIFIED w/o MenuitemID - Comment Out for MenuitemID
;TextText = %TextText%ID=%MenuitemID% ; ****VERIFIED when used with DllCall( "GetMenuItemID" ONLY ***
}
}
CoordMode, Tooltip, Screen
Tooltip, % TextText ? MenuitemID " : " . TextText : "", 0, 0
return
ESC::ExitApp
/***************************************************************
* Micha - Returns the TEXT of a menu entry (standard, context, popup & ahk menus only!!!)
***************************************************************
*/
GetContextMenuText(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768 ; Get Class of Menu/Menuitem
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;Allocate a struct for MenuItemInfo. It contains all the data of a Menu/Menuitem
VarSetCapacity(MenuItemInfo, 200, 0)
;Set Size of Struct [48] to the first member
InsertInteger(48, MenuItemInfo, 0, 4)
;Retrieve string MIIM_STRING = 0x40 = 64 (/ MIIM_TYPE = 0x10 = 16)
InsertInteger(64, 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)
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)
;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 ;-)
InsertInteger(GetMenuItemInfoRes, MenuItemInfo, 40, 4)
InsertInteger(&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
}
/***************************************************************
* Micha - returns the count of menu items
***************************************************************
*/
GetContextMenuCount(hWnd)
{
WinGetClass, WindowClass, ahk_id %hWnd%
;All popups should have the window class #32768
if WindowClass <> #32768
{
return 0
}
;Retrieve menu handle from window
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
menuitemcount:=DllCall("GetMenuItemCount",UInt,hMenu)
Return, menuitemcount
}
/***************************************************************
* Micha - returns the state of a menu entry
***************************************************************
*/
GetContextMenuState(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;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
InsertInteger(48, MenuItemInfo, 0, 4)
;Get only Flags from dllcall GetMenuItemInfo MIIM_TYPE = 1
InsertInteger(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)
return GetMenuItemInfoRes
}
GetMenu(hMenu)
{
Loop, % DllCall("GetMenuItemCount", "Uint", hMenu)
{
idx := A_Index - 1
idn := DllCall("GetMenuItemID", "Uint", hMenu, "int", idx)
nSize++ := DllCall("GetMenuString", "Uint", hMenu, "int", idx, "Uint", 0, "int", 0, "Uint", 0x400)
VarSetCapacity(sString, nSize)
DllCall("GetMenuString", "Uint", hMenu, "int", idx, "str", sString, "int", nSize, "Uint", 0x400) ;MF_BYPOSITION
If !sString
sString := "---------------------------------------"
sContents .= idx . " : " . idn . A_Tab . A_Tab . sString . "`n"
;msgbox idn=%idn%
If (idn = -1) && (hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", idx))
sContents .= GetMenu(hSubMenu)
}
Return sContents
}
;/*
; *********************************
; Original versions of ExtractInteger and InsertInteger provided by Chris
; - from the AutoHotkey help file - Version 1.0.37.04
; *********************************
; *********************************
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
SourceAddress := &pSource + pOffset ; Get address and apply the caller's offset.
result := 0 ; Init prior to accumulation in the loop.
Loop %pSize% ; For each byte in the integer:
{
result := result | (*SourceAddress << 8 * (A_Index - 1)) ; Build the integer from its bytes.
SourceAddress += 1 ; Move on to the next byte.
}
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset
; are altered in it. The caller must ensure that pDest has sufficient capacity.
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index - 1, UInt, 1 ; Write one byte.
, UChar, (pInteger & mask) >> 8 * (A_Index - 1)) ; This line is auto-merged with above at load-time.
mask := mask << 8 ; Set it up for isolation of the next byte.
}
} |
_________________ AutoHotFile - ToolTip(n,text,title,options) |
|
| Back to top |
|
 |
txquestor
Joined: 22 Aug 2009 Posts: 294
|
Posted: Sun Sep 13, 2009 2:40 am Post subject: Solution to MenuSpy |
|
|
Thanks for the quick response HotKeyIt.
The code you suggested is correct, however, the location breaks
the dynamic tooltip updatiing.
I moved it to the "IsEnable" section of the script. IT WORKS!
Thanks for all great work of Micha, Majkinetor,Sean & HotKeyIt
How to use this script.
1. Open an application with standards menus. Example: Notepad
2. Run this script
3. Select a Menu, try the EDIT menu.
4. Start moving slowly thru each menuitem
5. The Tooltip appears in the upper left corner of the desktop window
6. The tooltip dynamically updates with the menuitem's ID, Name & Hotkey
The ID is the "GetMenuItemID" function - see MSDN.
It's the value you see in WinInspector and you use in a PostMessage to select a specific menuitem.
As I mentioned above. This works on any type of menu;
standard, context, popup,tray & ahk menus in a tooltip
Even IExplorer, Explorer, and many others.
If it doesn't work on a menu. Then it's NOT a STANDARD Menu!!
You'll need to customize it to suit your needs.
Here's the finished code.
| Code: | ; MenuSpy 1.0
; by TxQuestor
; 9/12/09
; It dynamically displays the menuitem ID, Name & Hotkey in a tooltip as user moves thru each menuitem.
; This script uses part or all of these Menu Scripts
; Micha: GetContext Menu - http://www.autohotkey.com/forum/topic21451.html
; Majkinetor: MMenu - http://www.autohotkey.com/forum/topic17674.html
; Sean: GetInfo fromContext Menu - http://www.autohotkey.com/forum/viewtopic.php?p=137692.html
; HotKeyIt - created code to add the "GetMenuItemID" value to the MenuSpy Tooltip.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#Persistent
SetTimer, Demo, 500
return
Demo:
;constants
MFS_HILITE = 0x80
WinGet hWnd, ID, A
hMenu := DllCall("GetMenu", "UInt", hWnd)
MouseGetPos, MouseScreenX, MouseScreenY, MouseWindowUID, MouseControlID
WinGet,ControlHwnd, ID,ahk_id %MouseWindowUID%
;Get count of menu items
ContextMenCnt := GetContextMenuCount(ControlHwnd)
if ContextMenCnt < 1
{
Tooltip,
}
;Read info for each menu item on Highlight
loop, %ContextMenCnt%
{
IsEnabled := GetContextMenuState(ControlHwnd, a_index-1)
; Uses SendMessage to get the "GetMenuItemID" value
SendMessage, 0x01E1, , , , ahk_id %ControlHwnd%
MenuitemID := DllCall( "GetMenuItemID", "UInt", ErrorLevel, "Int", a_index-1 )
{
TextText =
if (IsEnabled & MFS_HILITE)
StrSize := GetContextMenuText(ControlHwnd, a_index-1)
TextText = %TextText%%a_index%:%StrSize%`n
StringTrimLeft, TextText, TextText, 2
StringReplace, TextText, TextText, `:, , All
TextText = %TextText%
}
}
CoordMode, Tooltip, Screen
Tooltip, % TextText ? "ID" . MenuitemID " : " . TextText : "", 0, 0
return
ESC::ExitApp
/***************************************************************
* Micha - Returns the TEXT of a menu entry (standard, context, popup & ahk menus only!!!)
***************************************************************
*/
GetContextMenuText(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768 ; Get Class of Menu/Menuitem
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;Allocate a struct for MenuItemInfo. It contains all the data of a Menu/Menuitem
VarSetCapacity(MenuItemInfo, 200, 0)
;Set Size of Struct [48] to the first member
InsertInteger(48, MenuItemInfo, 0, 4)
;Retrieve string MIIM_STRING = 0x40 = 64 (/ MIIM_TYPE = 0x10 = 16)
InsertInteger(64, 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)
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)
;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 ;-)
InsertInteger(GetMenuItemInfoRes, MenuItemInfo, 40, 4)
InsertInteger(&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
}
/***************************************************************
* Micha - returns the count of menu items
***************************************************************
*/
GetContextMenuCount(hWnd)
{
WinGetClass, WindowClass, ahk_id %hWnd%
;All popups should have the window class #32768
if WindowClass <> #32768
{
return 0
}
;Retrieve menu handle from window
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
menuitemcount:=DllCall("GetMenuItemCount",UInt,hMenu)
Return, menuitemcount
}
/***************************************************************
* Micha - returns the state of a menu entry
***************************************************************
*/
GetContextMenuState(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;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
InsertInteger(48, MenuItemInfo, 0, 4)
;Get only Flags from dllcall GetMenuItemInfo MIIM_TYPE = 1
InsertInteger(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)
return GetMenuItemInfoRes
}
GetMenu(hMenu)
{
Loop, % DllCall("GetMenuItemCount", "Uint", hMenu)
{
idx := A_Index - 1
idn := DllCall("GetMenuItemID", "Uint", hMenu, "int", idx)
nSize++ := DllCall("GetMenuString", "Uint", hMenu, "int", idx, "Uint", 0, "int", 0, "Uint", 0x400)
VarSetCapacity(sString, nSize)
DllCall("GetMenuString", "Uint", hMenu, "int", idx, "str", sString, "int", nSize, "Uint", 0x400) ;MF_BYPOSITION
If !sString
sString := "---------------------------------------"
sContents .= idx . " : " . idn . A_Tab . A_Tab . sString . "`n"
;msgbox idn=%idn%
If (idn = -1) && (hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", idx))
sContents .= GetMenu(hSubMenu)
}
Return sContents
}
;/*
; *********************************
; Original versions of ExtractInteger and InsertInteger provided by Chris
; - from the AutoHotkey help file - Version 1.0.37.04
; *********************************
; *********************************
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
SourceAddress := &pSource + pOffset ; Get address and apply the caller's offset.
result := 0 ; Init prior to accumulation in the loop.
Loop %pSize% ; For each byte in the integer:
{
result := result | (*SourceAddress << 8 * (A_Index - 1)) ; Build the integer from its bytes.
SourceAddress += 1 ; Move on to the next byte.
}
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset
; are altered in it. The caller must ensure that pDest has sufficient capacity.
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index - 1, UInt, 1 ; Write one byte.
, UChar, (pInteger & mask) >> 8 * (A_Index - 1)) ; This line is auto-merged with above at load-time.
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
|
_________________
"Man's quest for knowledge is an expanding series whose limit is infinity" |
|
| Back to top |
|
 |
txquestor
Joined: 22 Aug 2009 Posts: 294
|
Posted: Tue Sep 15, 2009 7:36 pm Post subject: [SOLVED] Add MenuitemID to dynamic menuitem tooltip |
|
|
"MenuSpy" Solved
Dynamically display a Menuitem's ID, Name & Hotkey in a Toolip as user moves thru each Menu's Menuitem
Thanks for all great work of Micha, Majkinetor,Sean & HotKeyIt
I used all, part or ideas from their Menu scripts to solve dynamic tooltip of menuitems
How to use this script.
1. Open an application with standards menus. Example: Notepad
2. Run this script
3. Select a Menu, try the EDIT menu.
4. Start moving slowly thru each menuitem
5. The Tooltip appears in the upper left corner of the desktop window
6. The tooltip dynamically updates with the menuitem's ID, Name & Hotkey
The ID is the "GetMenuItemID" function - see MSDN for details.
It's the value you see in WinInspector and you use the value in a PostMessage to select a specific menuitem.
As I mentioned above. This works on any type of menu;
standard, context, popup,tray & ahk menus in a tooltip
Even IExplorer, Explorer, and many others.
If it doesn't work on a menu. Then it's NOT a STANDARD Menu!!
You'll need to customize it to suit your needs.
Here's the finished code.
| Code: |
; MenuSpy
; by TxQuestor
; 09/12/2009
; It dynamically displays a Menu's menuitem Name & Hotkey in a tooltip as user moves thru each menuitem.
; Micha: GetContext Menu - http://www.autohotkey.com/forum/topic21451.html
; Sean: GetInfo fromContext Menu - http://www.autohotkey.com/forum/viewtopic.php?p=137692.html
; Majkinetor: MMenu - http://www.autohotkey.com/forum/topic17674.html
; HotKeyIt: created the code to add the MenuitemID to MenuSpy
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#Persistent
SetTimer, Demo, 500
return
Demo:
; Constants
MFS_HILITE = 0x80
WinGet hWnd, ID, A
hMenu := DllCall("GetMenu", "UInt", hWnd) ; VERIFIED for TextText
MouseGetPos, MouseScreenX, MouseScreenY, MouseWindowUID, MouseControlID
WinGet,ControlHwnd, ID,ahk_id %MouseWindowUID%
;Get count of menu items
ContextMenCnt := GetContextMenuCount(ControlHwnd)
if ContextMenCnt < 1
{
Tooltip,
}
;Read info for each menu item on IsEnabled & Highlight
loop, %ContextMenCnt%
{
; Get the Menuitem State & send Message to Menuitem to retrieve the "GetMenuItemID" value
IsEnabled := GetContextMenuState(ControlHwnd, a_index-1)
SendMessage, 0x01E1, , , , ahk_id %ControlHwnd%
; Errorlevel is set by SendMessage. It contains the ID handle to the menuitem not the same as wID in MIIM_ID from GetMenuItemInfo Function ()
MenuitemID := DllCall( "GetMenuItemID", "UInt", ErrorLevel, "Int", a_index-1 ) ; gets MenuitemID to show in Tooltip
{
TextText =
if (IsEnabled & MFS_HILITE) ; If Menuitem is Enabled & Highlighted get the Values for it's ID, Name & Hotkey
StrSize := GetContextMenuText(ControlHwnd, a_index-1) ; Gets the Name & Hotkey for a Menuitem
TextText = %TextText%%a_index%:%StrSize%`n
StringTrimLeft, TextText, TextText, 2
StringReplace, TextText, TextText, `:, , All
}
}
CoordMode, Tooltip, Screen
Tooltip, % TextText ? "ID" . MenuitemID " : " . TextText : "", ; Displays Menuitem's ID, Name & Hotkey
return
ESC::ExitApp
/***************************************************************
* Micha - Returns the TEXT of a menu entry (standard, context, popup & ahk menus only!!!)
***************************************************************
*/
GetContextMenuText(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768 ; Get Class of Menu/Menuitem
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;Allocate a struct for MenuItemInfo. It contains all the data of a Menu/Menuitem
VarSetCapacity(MenuItemInfo, 200, 0)
;Set Size of Struct [48] to the first member
InsertInteger(48, MenuItemInfo, 0, 4)
;Retrieve string MIIM_STRING = 0x40 = 64 (/ MIIM_TYPE = 0x10 = 16)
InsertInteger(64, 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)
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)
;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 ;-)
InsertInteger(GetMenuItemInfoRes, MenuItemInfo, 40, 4)
InsertInteger(&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
}
/***************************************************************
* Micha - returns the count of menu items
***************************************************************
*/
GetContextMenuCount(hWnd)
{
WinGetClass, WindowClass, ahk_id %hWnd%
;All popups should have the window class #32768
if WindowClass <> #32768
{
return 0
}
;Retrieve menu handle from window
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
menuitemcount:=DllCall("GetMenuItemCount",UInt,hMenu)
Return, menuitemcount
}
/***************************************************************
* Micha - returns the state of a menu entry
***************************************************************
*/
GetContextMenuState(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;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
InsertInteger(48, MenuItemInfo, 0, 4)
;Get only Flags from dllcall GetMenuItemInfo MIIM_TYPE = 1
InsertInteger(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)
return GetMenuItemInfoRes
}
;***************************************************************
; Majkinetor's - Get Menu's MenuitemInfo
;***************************************************************
GetMenu(hMenu)
{
Loop, % DllCall("GetMenuItemCount", "Uint", hMenu)
{
idx := A_Index - 1
idn := DllCall("GetMenuItemID", "Uint", hMenu, "int", idx)
nSize++ := DllCall("GetMenuString", "Uint", hMenu, "int", idx, "Uint", 0, "int", 0, "Uint", 0x400)
VarSetCapacity(sString, nSize)
DllCall("GetMenuString", "Uint", hMenu, "int", idx, "str", sString, "int", nSize, "Uint", 0x400) ;MF_BYPOSITION
If !sString
sString := "---------------------------------------"
sContents .= idx . " : " . idn . A_Tab . A_Tab . sString . "`n"
;msgbox idn=%idn%
If (idn = -1) && (hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", idx))
sContents .= GetMenu(hSubMenu)
}
Return sContents
}
;/*
; *********************************
; Original versions of ExtractInteger and InsertInteger provided by Chris
; - from the AutoHotkey help file - Version 1.0.37.04
; *********************************
; *********************************
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
SourceAddress := &pSource + pOffset ; Get address and apply the caller's offset.
result := 0 ; Init prior to accumulation in the loop.
Loop %pSize% ; For each byte in the integer:
{
result := result | (*SourceAddress << 8 * (A_Index - 1)) ; Build the integer from its bytes.
SourceAddress += 1 ; Move on to the next byte.
}
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset
; are altered in it. The caller must ensure that pDest has sufficient capacity.
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index - 1, UInt, 1 ; Write one byte.
, UChar, (pInteger & mask) >> 8 * (A_Index - 1)) ; This line is auto-merged with above at load-time.
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
|
_________________
"Man's quest for knowledge is an expanding series whose limit is infinity" |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|