 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
jsmain
Joined: 11 Jul 2005 Posts: 81
|
Posted: Sat Aug 04, 2007 11:23 pm Post subject: Menu Item State. |
|
|
I've been researching but I'm now confused...
I have a menu item I wish to check the state of before making any alterations....
It's a Pause menu item in my favorite music application.
I want to configure it so that if it is in a pause state, and I hit the play button, it will release the pause by toggling this menu. Obviously, if it is not set, I don't want to set it when I hit play from my remote control.
The Menu ID is 40121 for this item. Physically, it is the 2nd item in the 4th menu.
{File, Edit, View, Control, then under control, is play, then pause.}
My biggest problem is retrieving the info using GetMenuItemInfo.
I just don't understand the layout for this DllCall.
so far I have the following.
| Code: | WinGet, hWnd, ID, OtsDJ - Licensed
hMenu :=DllCall("GetMenu",Uint,hWnd,Uint)
hSubMenu :=DllCall("GetSubMenu",Uint,hMenu,int,3)
SubMenuID :=DllCall("GetMenuItemID",Uint,hSubMenu,Uint,1,Uint)
msgbox % SubMenuID
|
This gives my the proper ID, verified with MS Spy++ utility.
When I add the following code, I get 0, no matter the state of this item.
Obviously it's in the info statement arguments.
| Code: | Info :=DllCall("GetMenuItemInfo", Uint, hMenu, Uint, 3, Uint, 1, "int", &MenuItemInfo)
msgbox % Info |
Could someone help me understand what I'm doing wrong, and what I need to do to get this information properly?
Thanks _________________ Jeff Main |
|
| Back to top |
|
 |
jsmain
Joined: 11 Jul 2005 Posts: 81
|
Posted: Sat Aug 04, 2007 11:32 pm Post subject: |
|
|
BTW, I've also tried this in notepad, trying to determine the state of the word wrap menu item ID 32...
| Code: | WinGet, hWnd, ID, Untitled - Notepad
hMenu :=DllCall("GetMenu",Uint,hWnd,Uint)
hSubMenu :=DllCall("GetSubMenu",Uint,hMenu,int,2)
SubMenuID :=DllCall("GetMenuItemID",Uint,hSubMenu,Uint,0,Uint)
msgbox % SubMenuID
Info :=DllCall("GetMenuItemInfo",Uint,hMenu,Uint,3,Uint,1,"int",&MenuItemInfo)
msgbox % Info |
My reference sources are as follows...
http://www.autohotkey.com/forum/viewtopic.php?t=21451
http://www.autohotkey.com/forum/viewtopic.php?t=8492 _________________ Jeff Main |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2558 Location: Australia, Qld
|
Posted: Sun Aug 05, 2007 3:56 am Post subject: |
|
|
Here's a basic example:
| Code: | ifWinNotExist, Untitled - Notepad
{
Run, notepad.exe
WinWait, Untitled - Notepad
}
WinGet, hWnd, ID, Untitled - Notepad
hMenu :=DllCall("GetMenu", "Uint", hWnd)
hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", 2)
; Set the capacity of mii to sizeof(MENUITEMINFO)
VarSetCapacity(mii, 48, 0)
; Set the cbSize field to sizeof(MENUITEMINFO)
NumPut(48, mii, 0)
; Set the mask to whatever you want to retrieve.
; In this case I set it to MIIM_STATE=1.
NumPut(1, mii, 4)
; Note that menu item positions are zero-based.
DllCall("GetMenuItemInfo", "UInt", hSubMenu, "UInt", 0, "UInt", 1, "UInt", &mii)
; Get the state field out of the struct.
fState := NumGet(mii, 12)
if (fState & 0x8) ; MFS_CHECKED
MsgBox Word Wrap is enabled!
else
MsgBox Word Wrap is disabled!
/* Reference: MSDN
typedef struct tagMENUITEMINFO {
UINT cbSize;
UINT fMask;
UINT fType;
UINT fState;
UINT wID;
HMENU hSubMenu;
HBITMAP hbmpChecked;
HBITMAP hbmpUnchecked;
ULONG_PTR dwItemData;
LPTSTR dwTypeData;
UINT cch;
HBITMAP hbmpItem;
} MENUITEMINFO, *LPMENUITEMINFO;
BOOL GetMenuItemInfo( HMENU hMenu,
UINT uItem,
BOOL fByPosition,
LPMENUITEMINFO lpmii
);
*/
/* Reference: Platform SDK Headers
#if(WINVER >= 0x0400)
#define MIIM_STATE 0x00000001
#define MIIM_ID 0x00000002
#define MIIM_SUBMENU 0x00000004
#define MIIM_CHECKMARKS 0x00000008
#define MIIM_TYPE 0x00000010
#define MIIM_DATA 0x00000020
#endif /* WINVER >= 0x0400 */
#if(WINVER >= 0x0500)
#define MIIM_STRING 0x00000040
#define MIIM_BITMAP 0x00000080
#define MIIM_FTYPE 0x00000100
...
#define MFS_GRAYED 0x00000003L
#define MFS_DISABLED MFS_GRAYED
#define MFS_CHECKED MF_CHECKED
#define MFS_HILITE MF_HILITE
#define MFS_ENABLED MF_ENABLED
#define MFS_UNCHECKED MF_UNCHECKED
#define MFS_UNHILITE MF_UNHILITE
...
#define MF_ENABLED 0x00000000L
#define MF_UNCHECKED 0x00000000L
#define MF_CHECKED 0x00000008L
#define MF_UNHILITE 0x00000000L
#define MF_HILITE 0x00000080L
*/
|
Strangely, it seems to report "disabled" until you actually open the Format menu (even if you don't change anything.) I guess Notepad doesn't actually set the checkmark until then.
Your notepad example has a few issues:- You haven't set the capacity, cbSize, or fMask of MenuItemInfo.
- You're getting the state of an item in hMenu - Word Wrap would be in hSubMenu.
- Perhaps this is different for you, but on Vista, "Word Wrap" is the first item in the menu - position 0. (You've used position 3.)
Also, I'd recommend enclosing Uint in quotes ("UInt"). Though it does work without quotes in DllCall, it doesn't in NumGet, etc. It also creates an empty variable named "Uint".
FYI, GetMenuItemInfo sets values in the structure you pass it. The return value isn't menu item information, but a value indicating whether the function succeeded. | Quote: | If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, use the GetLastError function. |
|
|
| Back to top |
|
 |
jsmain
Joined: 11 Jul 2005 Posts: 81
|
Posted: Sun Aug 05, 2007 3:56 pm Post subject: |
|
|
Thanks for that, and sorry about the typos... I was using a different machine for the testing, and obviously didn't change everything I should have, and would have caught in a direct copy & paste.
After an upgrade to the latest AHK, it works just fine. _________________ Jeff Main |
|
| Back to top |
|
 |
jsmain
Joined: 11 Jul 2005 Posts: 81
|
Posted: Mon Aug 06, 2007 10:45 pm Post subject: |
|
|
lexikos,
This worked better in my app than it did with notepad. However, I now need to understand how to go 1 level deeper. I've been able to access all the first level menus with this script, but there are many more menus that I want to determine the state of that subs of the primary menu.
In this case again, it's OtsDJ, the Options menu (5th menu from the left, index 4) then the 13th menu down, then the 1st option on sub menu to the right. _________________ Jeff Main |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2558 Location: Australia, Qld
|
Posted: Tue Aug 07, 2007 7:30 am Post subject: |
|
|
Simply call GetSubMenu for each level deeper: | Code: | | hSubSubMenu := DllCall("GetSubMenu", "Uint", hSubMenu, "int", SubSubMenu_PositionWithinSubMenu) |
|
|
| Back to top |
|
 |
jsmain
Joined: 11 Jul 2005 Posts: 81
|
Posted: Tue Aug 07, 2007 12:01 pm Post subject: |
|
|
Cool!
Thank you very much!  _________________ Jeff Main |
|
| Back to top |
|
 |
Obi Guest
|
Posted: Mon Jun 23, 2008 2:32 pm Post subject: Subroutine |
|
|
I wrote a function that gives back whether a menu item of a window is checked or not (works even with hidden windows, but then turn DetectHiddenWindows On). Here is the Code:
| Code: | isMenuItemChecked(yourMenuPos, yourSubMenuPos, yourWindow)
{
WinGet, hWnd, ID, %yourWindow%
hMenu :=DllCall("GetMenu", "Uint", hWnd)
hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", yourMenuPos)
VarSetCapacity(mii, 48, 0)
NumPut(48, mii, 0)
NumPut(1, mii, 4)
DllCall("GetMenuItemInfo", "UInt", hSubMenu, "UInt", yourSubMenuPos, "UInt", 1, "UInt", &mii)
fState := NumGet(mii, 12)
if (fState & 0x8)
return 1
else
return 0
} |
In my opinion that should be a general feature in Autohotkey. Perhaps in the next Version.
How could i check Menu of Righ Click Tray icons if checked?
Regards |
|
| Back to top |
|
 |
Obi Guest
|
Posted: Mon Jun 23, 2008 3:02 pm Post subject: |
|
|
Sorry forgot to mention usage:
In the case of checking wordwrap in notepad (your example above) try:
isMenuItemChecked(2, 0, "ahk_class Notepad") |
|
| Back to top |
|
 |
Obi Guest
|
Posted: Tue Jun 24, 2008 12:48 am Post subject: |
|
|
| Lexikos wrote: | Here's a basic example:
Strangely, it seems to report "disabled" until you actually open the Format menu (even if you don't change anything.) I guess Notepad doesn't actually set the checkmark until then. |
Your're right in the mark.
To update the menu you have to activate it, the fastest way is to use postmessage:
| Code: | | PostMessage, 0x112, 0xF100,,, ahk_class Notepad |
This line activates menu directly. (0x112 = WM_SYSCOMMAND)
Perhaps insert a "sleep, 100" in between. And then:
| Code: | PostMessage, 0x100, 0x1B,,, ahk_class Notepad
PostMessage, 0x101, 0x1B,,, ahk_class Notepad |
...with this 2 lines you press ESC in your window. (WM_KEYDOWN= 0x100, WM_KEYUP = 0x101, 0x1B = VK_ESCAPE)
Now you have updatet your menu item state.
Now it should show the rights state. |
|
| 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
|