• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 218
  • Last Modified:

Clicking on the desktop won't minimise popup menu

I've created a small app which runs in the system tray. The popup works fine except if I decide not to use any of the options and just click on the desktop to minimise the menu again (standard behaviour, basically) the menu just stays there until I select something. Can anyone tell me what I need to add to enable the menu to close? Here is the code:

' Type passed to Shell_NotifyIcon
Private Type NotifyIconData
  Size As Long
  Handle As Long
  ID As Long
  Flags As Long
  CallBackMessage As Long
  Icon As Long
  Tip As String * 64
End Type

' Constants for managing System Tray tasks, foudn in shellapi.h
Private Const AddIcon = &H0
Private Const ModifyIcon = &H1
Private Const DeleteIcon = &H2

Private Const WM_MOUSEMOVE = &H200
Private Const WM_LBUTTONDBLCLK = &H203
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202

Private Const WM_RBUTTONDBLCLK = &H206
Private Const WM_RBUTTONDOWN = &H204
Private Const WM_RBUTTONUP = &H205

Private Const MessageFlag = &H1
Private Const IconFlag = &H2
Private Const TipFlag = &H4
     
Private Declare Function Shell_NotifyIcon _
  Lib "shell32" Alias "Shell_NotifyIconA" ( _
  ByVal Message As Long, Data As NotifyIconData) As Boolean

Private Data As NotifyIconData

Private Sub Form_Terminate()
  DeleteIconFromTray
End Sub

Private Sub AddIconToTray()

  Data.Size = Len(Data)
  Data.Handle = hWnd
  Data.ID = vbNull
  Data.Flags = IconFlag Or TipFlag Or MessageFlag
  Data.CallBackMessage = WM_MOUSEMOVE
  Data.Icon = Icon
  Data.Tip = Status1$ & vbNullChar
  Call Shell_NotifyIcon(AddIcon, Data)

End Sub

Private Sub DeleteIconFromTray()
  Call Shell_NotifyIcon(DeleteIcon, Data)
End Sub

Private Sub Form_MouseMove(Button As Integer, _
  Shift As Integer, X As Single, Y As Single)
 
  Dim Message As Long
  Message = X / Screen.TwipsPerPixelX
 
  Select Case Message
    Case WM_LBUTTONDBLCLK
      Visible = Not Visible
      WindowState = Abs(Not Visible)
     
     Case WM_RBUTTONDOWN
     Call Me.PopupMenu(rmenu, MenuVisible)
0
The__Saint
Asked:
The__Saint
  • 4
  • 3
  • 2
  • +1
1 Solution
 
BurbbleCommented:
Need the rest of your code :-)

Here's how I always do it:

modSysTray
-----
Public Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long

Public Type NOTIFYICONDATA
    cbSize As Long
    hWnd As Long
    uID As Long
    uFlags As Long
    uCallbackMessage As Long
    hIcon As Long
    sTip As String * 64
End Type

Public SysTrayIcon As NOTIFYICONDATA

Public Const NIM_ADD = &H0
Public Const NIM_MODIFY = &H1
Public Const NIM_DELETE = &H2
Public Const NIF_MESSAGE = &H1
Public Const NIF_ICON = &H2
Public Const NIF_TIP = &H4
Public Const SW_RESTORE = 9
Public Const SW_MINIMIZE = 6
Public Const WM_MOUSEMOVE = &H200
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
Public Const WM_LBUTTONDBLCLK = &H203
Public Const WM_RBUTTONDOWN = &H204
Public Const WM_RBUTTONUP = &H205
Public Const WM_RBUTTONDBLCLK = &H206

Public Function SetIcon(IconPath As String)
    frmIcon.Icon = LoadPicture(IconPath)
    SysTrayIcon.hIcon = frmIcon.Icon
    Shell_NotifyIcon NIM_MODIFY, SysTrayIcon
End Function

Public Function SetIconToolTip(Text As String)
    SysTrayIcon.sTip = Text & vbNullChar
    Shell_NotifyIcon NIM_MODIFY, SysTrayIcon
End Function
-----

frmIcon
-----
Private Sub Form_Load()
    SysTrayIcon.cbSize = Len(SysTrayIcon)
    SysTrayIcon.hWnd = frmIcon.hWnd
    SysTrayIcon.uID = vbNull
    SysTrayIcon.uFlags = NIF_MESSAGE Or NIF_ICON Or NIF_TIP
    SysTrayIcon.uCallbackMessage = WM_MOUSEMOVE
    SysTrayIcon.hIcon = frmIcon.Icon
    SysTrayIcon.sTip = "InfiniTalk - Offline" & vbNullChar
    Shell_NotifyIcon NIM_ADD, SysTrayIcon
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Dim IconEvent As Long

    IconEvent = X / Screen.TwipsPerPixelX

    Select Case IconEvent
        Case WM_RBUTTONUP
            PopupMenu frmIcon.mnuMain
        Case WM_LBUTTONUP
            If frmMain.Visible = False Or (frmMain.WindowState = vbMinimized And frmMain.Visible = True) Then
                frmMain.WindowState = vbNormal
                frmMain.Visible = True
            ElseIf frmMain.Visible = True Then
                frmMain.Visible = False
            End If
    End Select
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    Shell_NotifyIcon NIM_DELETE, SysTrayIcon
    Unload frmMain
    Set frmMain = Nothing
    Unload frmIcon
    Set frmIcon = Nothing
    End
End Sub
-----

You can modify it to your liking...

-Burbble
0
 
The__SaintAuthor Commented:
Looking through this I couldn't see anything which stood out as to be the cause of my issue. I was hoping there maybe just a minor change I need to make to mine so I appreciate perhaps I didn't include everything I should have! Here is the lot (apologies for not cutting this slightly but I figure it's easier to look at in full):


' Type passed to Shell_NotifyIcon
Private Type NotifyIconData
  Size As Long
  Handle As Long
  ID As Long
  Flags As Long
  CallBackMessage As Long
  Icon As Long
  Tip As String * 64
End Type

' Constants for managing System Tray tasks, foudn in shellapi.h
Private Const AddIcon = &H0
Private Const ModifyIcon = &H1
Private Const DeleteIcon = &H2

Private Const WM_MOUSEMOVE = &H200
Private Const WM_LBUTTONDBLCLK = &H203
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202

Private Const WM_RBUTTONDBLCLK = &H206
Private Const WM_RBUTTONDOWN = &H204
Private Const WM_RBUTTONUP = &H205

Private Const MessageFlag = &H1
Private Const IconFlag = &H2
Private Const TipFlag = &H4
     
Private Declare Function Shell_NotifyIcon _
  Lib "shell32" Alias "Shell_NotifyIconA" ( _
  ByVal Message As Long, Data As NotifyIconData) As Boolean

Private Data As NotifyIconData



Private Sub Form_Terminate()
  DeleteIconFromTray
End Sub

Private Sub AddIconToTray()

  Data.Size = Len(Data)
  Data.Handle = hWnd
  Data.ID = vbNull
  Data.Flags = IconFlag Or TipFlag Or MessageFlag
  Data.CallBackMessage = WM_MOUSEMOVE
  Data.Icon = Icon
  Data.Tip = Status1$ & vbNullChar
  Call Shell_NotifyIcon(AddIcon, Data)

End Sub

Private Sub DeleteIconFromTray()
  Call Shell_NotifyIcon(DeleteIcon, Data)
End Sub

Private Sub Form_MouseMove(Button As Integer, _
  Shift As Integer, X As Single, Y As Single)
 
  Dim Message As Long
  Message = X / Screen.TwipsPerPixelX
 
  Select Case Message
    Case WM_LBUTTONDBLCLK
      Visible = Not Visible
      WindowState = Abs(Not Visible)
     
     Case WM_RBUTTONDOWN
     Call Me.PopupMenu(rmenu, MenuVisible)

  End Select
End Sub


Private Sub MExit_Click()
Unload Form1
End Sub

Private Sub minbutton_Click()
AddIconToTray
Visible = False
End Sub
Private Sub MNIProxy_Click(Index As Integer)
Call NIPROXY_Click
End Sub

Private Sub MNoProxy_Click(Index As Integer)
Call NOPROXY_Click
End Sub

Private Sub MProxyDev_Click(Index As Integer)
Call PROXYDEV_Click
End Sub

Private Sub MStreaming_Click(Index As Integer)
Call stream_Click
End Sub

Private Sub NIPROXY_Click()

<code for subroutine>

End Sub

Private Sub Form_Load()

<Stuff>

Private Sub PROXYDEV_Click()
<code for subroutine>

Private Sub NOPROXY_Click()
<code for subroutine>

Private Sub stream_Click()
<code for subroutine>

Private Sub ToggleState()
   Visible = Not Visible
   WindowState = GetWindowState(Not Visible)
 End Sub

 Private Sub MenuVisible_Click()
   ToggleState
 End Sub
Private Function GetWindowState(ByVal Value As Boolean) As Integer

    GetWindowState = Abs(Value)
End Function

----------------------------------------------------------------------------------
Hope this make things clearer.

Cheers
0
 
BurbbleCommented:
Hmm, I don't know what to say... The only real difference is this line:

    Call Me.PopupMenu(rmenu, MenuVisible)

compared to this:

    PopupMenu rmenu

Try changing it and see if that makes a difference... Otherwise, I am stumped.

-Burbble
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
The__SaintAuthor Commented:
Thanks for your help Burbble, have tried changing it and it's exactly the same. I assumed it was standard behaviour of a popup menu to close when the desktop was clicked but obviously not!
I would think that I might need to add some code to the MenuVisible_Click procedure but I'm not sure how to detect for a right-click on the desktop. Of course, I may be barking up the wrong tree.
I'm going to up the points a bit as it doesn't appear to be quite a straightforward as I first thought it might be.
0
 
BurbbleCommented:
I don't know. I posted a pointer question to hopefully draw other Experts to this question.

Sorry I can't help, hopefulyl someone else can :/

-Burbble
0
 
zzzzzoocCommented:
The window from which the PopupMenu originates needs to have focus if I recall correctly.

Try using Call SetForegroundWindow(FormThatHasMenu.hWnd) before showing the PopupMenu.

Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long


0
 
nichiaCommented:
Taking the example from MS the call to SetForegroundWindow should do the trick, as zzzzzzzzzzzzzoooc has already mentioned.

Their example code:

Case WM_RBUTTONUP        '517 display popup menu
Result = SetForegroundWindow(Me.hwnd)
         Me.PopupMenu Me.mPopupSys
       End Select
0
 
nichiaCommented:
Note also they use the button UP message.

The MS example is here:

http://support.microsoft.com/support/kb/articles/Q176/0/85.asp

Hope it helps!
0
 
The__SaintAuthor Commented:
Yes this is what I needed. Problem solved. Thanks to everyone for taking time out, cheers Burble for bringing this to people attention and nichia for the link which helped finish it off. Much appreciated!
0
 
BurbbleCommented:
Interesting... Glad you got it working :-)

-Burbble
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 4
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now