Results 1 to 8 of 8

Thread: RESOLVED Get menu disabled status

  1. #1

    Thread Starter
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    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

  2. #2
    Frenzied Member
    Join Date
    Jul 2005
    Posts
    1,168

    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.

  3. #3

    Thread Starter
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    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.

  4. #4

    Thread Starter
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    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

  5. #5
    Frenzied Member
    Join Date
    Jul 2005
    Posts
    1,168

    Re: Get menu disabled status

    Here is the vb.net equivalent of the codes mentioned above:

    VB Code:
    1. ' make sure to import "Imports System.Runtime.InteropServices"
    2.  
    3.  Public Structure MENUITEMINFO
    4.         Public cbSize As Integer
    5.         Public fMask As Integer
    6.         Public fType As Integer
    7.         Public fState As Integer
    8.         Public wID As Integer
    9.         Public hSubMenu As Integer
    10.         Public hbmpChecked As Integer
    11.         Public hbmpUnchecked As Integer
    12.         Public dwItemData As Integer
    13.         Public dwTypeData As String
    14.         Public cch As Integer
    15.     End Structure
    16.  
    17.  
    18.     Public Const MFS_ENABLED = &H0
    19.     Public Const MFS_GRAYED = &H3
    20.     Public Const MIIM_STATE = &H1
    21.  
    22.     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
    23.     Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
    24.     Public Declare Function GetMenu Lib "user32" Alias "GetMenu" (ByVal hwnd As Integer) As Integer
    25.     Public Declare Function GetSubMenu Lib "user32" Alias "GetSubMenu" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
    26.  
    27.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    28.         Dim hWnd As Integer = FindWindow(Nothing, "Form1")
    29.         Dim hMenu As Integer = GetMenu(hWnd)
    30.         Dim menuItem As MENUITEMINFO
    31.  
    32.         menuItem.cbSize = Marshal.SizeOf(menuItem)
    33.         menuItem.fMask = MIIM_STATE
    34.  
    35.         Dim ret As Integer
    36.         ret = GetMenuItemInfo(hMenu, 0, True, menuItem)
    37.  
    38.         If ret <> 0 Then 'if ret is non-zero, then function succeeded
    39.             If menuItem.fState = MFS_GRAYED Then
    40.                 MsgBox("Menu item is disabled")
    41.             ElseIf menuItem.fState = MFS_ENABLED Then
    42.                 MsgBox("Menu item is enabled")
    43.             End If
    44.         End If
    45.  
    46.     End Sub
    47.  
    48.     Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    49.         Dim hWnd As Integer = FindWindow(Nothing, "Form1")
    50.         Dim hMenu As Integer = GetMenu(hWnd)
    51.         Dim hSubMenu As Integer = GetSubMenu(hMenu, 0)
    52.  
    53.         Dim menuItem As MENUITEMINFO
    54.  
    55.         menuItem.cbSize = Marshal.SizeOf(menuItem)
    56.         menuItem.fMask = MIIM_STATE
    57.  
    58.         Dim ret As Integer
    59.         ret = GetMenuItemInfo(hSubMenu, 0, True, menuItem)
    60.  
    61.         If ret <> 0 Then 'if ret is non-zero, then function succeeded
    62.             If menuItem.fState = MFS_GRAYED Then
    63.                 MsgBox("Menu item is disabled")
    64.             ElseIf menuItem.fState = MFS_ENABLED Then
    65.                 MsgBox("Menu item is enabled")
    66.             End If
    67.         End If
    68.     End Sub
    Last edited by benmartin101; Aug 31st, 2006 at 12:42 PM.

  6. #6

    Thread Starter
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    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.

  7. #7

    Thread Starter
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    Thumbs up 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:
    1. Const WM_COMMAND = &H111
    2. 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
    3. Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
    4. Public Declare Function GetMenu Lib "user32" Alias "GetMenu" (ByVal hwnd As Integer) As Integer
    5. Public Declare Function GetSubMenu Lib "user32" Alias "GetSubMenu" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
    6. Private Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
    7.             Dim hWnd As Integer = FindWindow(vbNullString, "[COLOR=Lime]AppTitle[/COLOR]")
    8.             Dim hMenu As Integer = GetMenu(hWnd)
    9.             Dim hSubMenu As Integer = GetSubMenu(hMenu, 0)
    10.             Dim hId As Integer = GetMenuItemID(hSubMenu, 0)
    11.  
    12.             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.

  8. #8

    Thread Starter
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    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:
    1. Const MF_GRAYED = &H1
    2. Private Declare Function BlockInput Lib "user32" (ByVal fBlock As Integer) As Integer    
    3. Private Declare Function GetForegroundWindow Lib "user32" () As Integer  
    4. Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Integer) As Integer
    5. Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer  
    6. Public Declare Function GetMenu Lib "user32" Alias "GetMenu" (ByVal hwnd As Integer) As Integer
    7. Public Declare Function GetSubMenu Lib "user32" Alias "GetSubMenu" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
    8. Private Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Integer, ByVal nPos As Integer) As Integer
    9. Public Declare Function GetMenuState Lib "user32" Alias "GetMenuState" (ByVal hMenu As Integer, ByVal wID As Integer, ByVal wFlags As Integer) As Integer

    VB Code:
    1. On Error Resume Next
    2.         Dim count as integer = 0
    3.         Dim SomeLimit as integer = [COLOR=Lime]YourLimit[/COLOR]
    4.         exeAppTitle.PriorityClass = ProcessPriorityClass.Normal
    5.         ForeGroundWindow = GetForegroundWindow
    6.         BlockInput(True)
    7.         Do
    8.             SetForegroundWindow(FindWindow(Nothing, "[COLOR=Lime]AppTitle[/COLOR]"))
    9.             If GetForegroundWindow = FindWindow(Nothing, "[COLOR=Lime]AppTitle[/COLOR]") Then
    10.                 SendKeys.Send("{F10}f")
    11.                 Exit Do
    12.             End If
    13.             count += 1
    14.             If count > [COLOR=Orange]Some Limit[/COLOR] then
    15.                Exit Do
    16.             End if
    17.         Loop
    18.         BlockInput(False)
    19.         SetForegroundWindow(ForeGroundWindow)
    20.  
    21.  
    22.         Dim hWnd As Integer = FindWindow(Nothing, "[COLOR=Lime]AppTitle[/COLOR]")
    23.         Dim hMenu As Integer = GetMenu(hWnd)
    24.         Dim hSubMenu As Integer = GetSubMenu(hMenu, [COLOR=Lime]0[/COLOR])
    25.         Dim hId As Integer = GetMenuItemID(hSubMenu, [COLOR=Lime]2[/COLOR])
    26.         exeAppTitle.PriorityClass = ProcessPriorityClass.Idle
    27.  
    28.  
    29.         If GetMenuState(hMenu, hId, MF_GRAYED Then
    30.             MessageBox.Show("menu disabled")
    31.         Else
    32.             MessageBox.Show("menu enabled")
    33.         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
  •  



Click Here to Expand Forum to Full Width