Determine if right click menu is shown


I built an Auto logoff mechanism in my application.
If user left system after he right click on one of my controls, and right click menu has appeared,
the auto logoff is working incorrectly - when I unload the form, the function that operate the pop up menu is still active.

I want to cancel the auto logoff if pop up menu is shown.
Is there a way to determine if a pop up menu is shown ?
Of course, I can set some flag before I open menus, but I prefer a better way

Who is Participating?
amebaConnect With a Mentor Commented:
Instead of cancelling logoff, cancel user's popup :-)

Private Sub Timer1_Timer()
    If GetCapture <> 0 Then
        On Error Resume Next
        SendKeys "{ESC}"
    End If
    ' your logoff proc.
End Sub
PopupMenu() and TrackPopupMenu(Ex) (API) both wait for returns before processing anything else so the thread will be "blocked". If your "Auto logoff mechanism" is within it's own thread (a Timer control for example), it won't be effected by it. Your only likely option is just to use a flag-variable to check if any PopupMenus are open at the time and I doubt there are any more efficient methods (will take note to any if they're posted). A few boolean variables shouldn't harm much.

You could always just create your own windows (WS_POPUP) and try to simulate PopupMenus though. You can avoid the input-asynchronous behavior that way (at a costly price however).

FYI, interested in possible solutions for this question also now.
I think the simplest way to do this would be to add a global boolean variable ie blnPopupShown

Then when you display a popup menu do the following

blnPopupShown = True
popupmeeu  ....
blnPopupShown = False

Then in your timeout feature just add
If Not blnPopUpshow Then
 timeout code
End If

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

you can check for the visibilty of the popupmenu, in case the menu is invisible at design time. something like this

if not myPop.Visible then unload me

as long as the popup is displayed the visible property returns true. once the popup is closed its visible property returns false.
If the menus are only used as popup, then you can just check the visibility of the menu.
If you don't use SetCapture in your code, you can use GetCapture to determine if popup window captured mouse.
GetCapture will return 0 if there is no popup shown, and <> 0 if your popup, or textbox's built-in popup menu is shown.  (If you are using SetCapture in your code, you know that it is similar in behavior, i.e. normally code waits for another mouse action and it should be treated the same as popup.)

' Form1, add menu mnuPop (visible=false) and a submenu
'        also, add Textbox and Timer (interval=1000)
Option Explicit
Private Declare Function GetCapture Lib "user32" () As Long

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbRightButton Then Me.PopupMenu Me.mnuPop
End Sub

Private Sub Timer1_Timer()
    Caption = GetCapture ' shows 0 or, if menu is shown, some value <>0
End Sub
GetCapture will also return non-zero, if your mouse action is in progress, e.g. you are holding mouse down and moving it.  Hope it is OK behavior.
zzzzzoocConnect With a Mentor Commented:
Interesting GetCapture idea. :)

There's another method which will check to see if a Popup-Menu window exists within your application's thread. This will include right-clicking on the title-bar and on the app's bar in the taskbar.



Private Sub Form_Load()
    Timer1.Interval = 1000
    Timer1.Enabled = True
End Sub
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Call Me.PopupMenu(mnuTest)
End Sub
Private Sub Timer1_Timer()
    If IsMenuOpen = True Then
        Me.Caption = "Menu=true"
        Me.Caption = "Menu=false"
    End If
End Sub


Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean
Public Function IsMenuOpen() As Boolean
    IsMenuOpen = Not EnumWindows(AddressOf EnumWindowsProc, 0)
End Function
Public Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean
    Dim sBuff As String * 256, iLen As Integer, sClass As String
    If GetWindowThreadProcessId(hWnd, 0) = App.ThreadID Then
        iLen = GetClassName(hWnd, sBuff, Len(sBuff))
        If iLen > 0 Then
            sClass = Left$(sBuff, iLen)
            If sClass = "#32768" Then
                EnumWindowsProc = False
                Exit Function
            End If
        End If
    End If
    EnumWindowsProc = True
End Function

My recommendation:
    Split: ameba {http:#10814855} & zzzzzooc {http:#10819088}

Any objections should be posted here in the next 4 days. After that time, the question will be closed.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.