|
-
Aug 30th, 2006, 02:11 PM
#1
Thread Starter
Fanatic Member
RESOLVED Get menu disabled status
I'm trying to verify that a program is still running, by getting the enabled status of a menu item. If it's disabled, the app is running, if it's enabled, then the app has stopped. Simple enough right?
Please help! This is what I have tried:
Code:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Integer) As Integer
Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
Private Declare Function IsWindowEnabled Lib "user32" (ByVal hwnd As Integer) As Integer
If FindWindow(vbNullString, "AppTitle") <> 0 Then
Dim hMenu, hSubMenu As Integer
hMenu = GetMenu(FindWindow(vbNullString, "AppTitle"))
hSubMenu = GetSubMenu(hMenu, 0)
If IsWindowEnabled(hSubMenu) Then
MessageBox.Show("App not running")
Else
MessageBox.Show("App running")
End If
Else
MessageBox.Show("App, is closed")
End If
Or should I try to use the MF_DISABLED constant with something?
Last edited by TTn; Sep 1st, 2006 at 07:55 AM.
Reason: Resolved
-
Aug 30th, 2006, 04:30 PM
#2
Frenzied Member
Re: Get menu disabled status
Try this...its in c++. I'm sure you could just translate it to vb.
Code:
HWND hwnd = FindWindow("Notepad", NULL);
HMENU hmenu = GetMenu(hwnd);
MENUITEMINFO * mInfo;
mInfo = new MENUITEMINFO();
mInfo->cbSize = sizeof(MENUITEMINFO);
mInfo->fMask = MIIM_STATE;
GetMenuItemInfo(hmenu, 0, true, mInfo); //the 2nd parameter is the index of the menu; 0-based.
if(mInfo->fState == MFS_DISABLED || mInfo->fState == MFS_GRAYED)
{
MessageBox(NULL, "Menu item is disabled", "", MB_OK);
}
return 0;
The code above is if you want to know the enabled/disabled status of the "main" menu item(such as File, Edit, View, Help, etc).
If you want to know the status of the submenu items(such as File->New, File->Open, etc.), then use the code below.
Code:
HWND hwnd = FindWindow("Notepad", NULL);
HMENU hmenu = GetMenu(hwnd);
HMENU hSubMenu = GetSubMenu(hmenu, 0);
MENUITEMINFO * mInfo;
mInfo = new MENUITEMINFO();
mInfo->cbSize = sizeof(MENUITEMINFO);
mInfo->fMask = MIIM_STATE;
GetMenuItemInfo(hSubMenu, 0, true, mInfo);
if(mInfo->fState == MFS_DISABLED || mInfo->fState == MFS_GRAYED)
{
MessageBox(NULL, "Menu item is disabled", "", MB_OK);
}
return 0;
Last edited by benmartin101; Aug 30th, 2006 at 04:37 PM.
-
Aug 30th, 2006, 04:52 PM
#3
Thread Starter
Fanatic Member
Re: Get menu disabled status
Ah thanks, I tried something similar to this with MF_DISABLED.
I should be able to get that to work with the type intialized, and rigged as a structure in VB.NET2003 like you've shown.
I'll let you know how it goes.
-
Aug 31st, 2006, 06:57 AM
#4
Thread Starter
Fanatic Member
Re: Get menu disabled status
No luck yet.
I've tried several variations, trying to convert the type declarations you've given, into structure declarations, for use in .NET.
It looks like it should work, but it's very frustrating thus far.
I also got detracted with someone elses samples, that lead nowhere.
Could you give a more detailed explaination of your sample.
Namely, the mInfo declaration and useage.
Also, what does == , and ->, and *, and || stand for?
I'm not finding a MIIM_STATE, what's the H& equal to?
Thanks
-
Aug 31st, 2006, 12:39 PM
#5
Frenzied Member
Re: Get menu disabled status
Here is the vb.net equivalent of the codes mentioned above:
VB Code:
' make sure to import "Imports System.Runtime.InteropServices"
Public Structure MENUITEMINFO
Public cbSize As Integer
Public fMask As Integer
Public fType As Integer
Public fState As Integer
Public wID As Integer
Public hSubMenu As Integer
Public hbmpChecked As Integer
Public hbmpUnchecked As Integer
Public dwItemData As Integer
Public dwTypeData As String
Public cch As Integer
End Structure
Public Const MFS_ENABLED = &H0
Public Const MFS_GRAYED = &H3
Public Const MIIM_STATE = &H1
Public Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" (ByVal hMenu As Integer, ByVal un As Integer, ByVal b As Boolean, ByRef lpMenuItemInfo As MENUITEMINFO) As Integer
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Public Declare Function GetMenu Lib "user32" Alias "GetMenu" (ByVal hwnd As Integer) As Integer
Public Declare Function GetSubMenu Lib "user32" Alias "GetSubMenu" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim hWnd As Integer = FindWindow(Nothing, "Form1")
Dim hMenu As Integer = GetMenu(hWnd)
Dim menuItem As MENUITEMINFO
menuItem.cbSize = Marshal.SizeOf(menuItem)
menuItem.fMask = MIIM_STATE
Dim ret As Integer
ret = GetMenuItemInfo(hMenu, 0, True, menuItem)
If ret <> 0 Then 'if ret is non-zero, then function succeeded
If menuItem.fState = MFS_GRAYED Then
MsgBox("Menu item is disabled")
ElseIf menuItem.fState = MFS_ENABLED Then
MsgBox("Menu item is enabled")
End If
End If
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim hWnd As Integer = FindWindow(Nothing, "Form1")
Dim hMenu As Integer = GetMenu(hWnd)
Dim hSubMenu As Integer = GetSubMenu(hMenu, 0)
Dim menuItem As MENUITEMINFO
menuItem.cbSize = Marshal.SizeOf(menuItem)
menuItem.fMask = MIIM_STATE
Dim ret As Integer
ret = GetMenuItemInfo(hSubMenu, 0, True, menuItem)
If ret <> 0 Then 'if ret is non-zero, then function succeeded
If menuItem.fState = MFS_GRAYED Then
MsgBox("Menu item is disabled")
ElseIf menuItem.fState = MFS_ENABLED Then
MsgBox("Menu item is enabled")
End If
End If
End Sub
Last edited by benmartin101; Aug 31st, 2006 at 12:42 PM.
-
Aug 31st, 2006, 06:22 PM
#6
Thread Starter
Fanatic Member
Re: Get menu disabled status
I have the same exact sample that I worked on afterwards, which is almost identical to yours.
Hmmm ...it's still not working on this app. Oh wait..... HA AHHH!!!
MIIM_STATE = &H1 is the only difference.
I was using MIIM_SUBMENU as in the API GUIDE example.
I also tried Marshal.SizeOf(), and Microsoft.VisualBasic.Len().
This should definately work now, I'll repost with the results.
Thank you very much sir.
-
Sep 1st, 2006, 07:50 AM
#7
Thread Starter
Fanatic Member
Re: Get menu disabled status
Okay, I did get this to work, however the menu must be clicked/opened in order for the status to update. This is a specific problem of the external app, so most people will be able to use this code just fine.
Ironically, I found a work around, that is specific to the app.
I simply click that menu item, and a particular window comes up only when inactive. Detect it, close it, and signal not active.
VB Code:
Const WM_COMMAND = &H111
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Public Declare Function GetMenu Lib "user32" Alias "GetMenu" (ByVal hwnd As Integer) As Integer
Public Declare Function GetSubMenu Lib "user32" Alias "GetSubMenu" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
Private Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
Dim hWnd As Integer = FindWindow(vbNullString, "[COLOR=Lime]AppTitle[/COLOR]")
Dim hMenu As Integer = GetMenu(hWnd)
Dim hSubMenu As Integer = GetSubMenu(hMenu, 0)
Dim hId As Integer = GetMenuItemID(hSubMenu, 0)
SendMessage(hWnd, WM_COMMAND, hId, 0)
Thank you for clearing this up Ben!
BTW, Always use MessageBox.Show, instead of MsgBox(), because it can mess up some execution tests.
If the point is to see if the flow got there, we don't want to actually mess up the flow from getting there.
Good habit, and example to others.
Last edited by TTn; Sep 1st, 2006 at 08:01 AM.
-
Sep 1st, 2006, 07:08 PM
#8
Thread Starter
Fanatic Member
Re: RESOLVED Get menu disabled status
If anyone needs a workaround for the menu update problem, that some apps may have, try this basic idea:
Insert a process component named exeAppTitle.
Use the API GetForegroundWindow, BlockInput, and SetForegroundWindow.
Declare an integer data type for the current ForeGroundWindow.
VB Code:
Const MF_GRAYED = &H1
Private Declare Function BlockInput Lib "user32" (ByVal fBlock As Integer) As Integer
Private Declare Function GetForegroundWindow Lib "user32" () As Integer
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Integer) As Integer
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Public Declare Function GetMenu Lib "user32" Alias "GetMenu" (ByVal hwnd As Integer) As Integer
Public Declare Function GetSubMenu Lib "user32" Alias "GetSubMenu" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
Private Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
Public Declare Function GetMenuState Lib "user32" Alias "GetMenuState" (ByVal hMenu As Integer, ByVal wID As Integer, ByVal wFlags As Integer) As Integer
VB Code:
On Error Resume Next
Dim count as integer = 0
Dim SomeLimit as integer = [COLOR=Lime]YourLimit[/COLOR]
exeAppTitle.PriorityClass = ProcessPriorityClass.Normal
ForeGroundWindow = GetForegroundWindow
BlockInput(True)
Do
SetForegroundWindow(FindWindow(Nothing, "[COLOR=Lime]AppTitle[/COLOR]"))
If GetForegroundWindow = FindWindow(Nothing, "[COLOR=Lime]AppTitle[/COLOR]") Then
SendKeys.Send("{F10}f")
Exit Do
End If
count += 1
If count > [COLOR=Orange]Some Limit[/COLOR] then
Exit Do
End if
Loop
BlockInput(False)
SetForegroundWindow(ForeGroundWindow)
Dim hWnd As Integer = FindWindow(Nothing, "[COLOR=Lime]AppTitle[/COLOR]")
Dim hMenu As Integer = GetMenu(hWnd)
Dim hSubMenu As Integer = GetSubMenu(hMenu, [COLOR=Lime]0[/COLOR])
Dim hId As Integer = GetMenuItemID(hSubMenu, [COLOR=Lime]2[/COLOR])
exeAppTitle.PriorityClass = ProcessPriorityClass.Idle
If GetMenuState(hMenu, hId, MF_GRAYED Then
MessageBox.Show("menu disabled")
Else
MessageBox.Show("menu enabled")
End If
Last edited by TTn; Sep 7th, 2006 at 06:23 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|