From: Norm on
Hi,
I have an app that runs in the system tray and you click on the icon to use
functions within the app. Occasionally I have noticed that for some reason
the app is running but no icon is showing in the system tray, which means
you cannot access the app.

When I start a new instance of the app it tells me that the app is already
running and then shuts down the new instance. I have tried the following
code, but since the app is only running in the system tray I cannot show the
app.

Is there a better way to do this so that I can get the apps icon to appear
in the system tray?

Thanks,
Norm

Code:

Watch for Line Wrap

I call FindWindowHandle which will get the hwnd form a partial Window Title
and then once I have the hwnd I can get the correct and full window title
and try to show that, but it does not show anything since the app is running
in the system tray.


Option Explicit

Public Type POINTAPI
x As Long
y As Long
End Type

Private Type WINDOWPLACEMENT

Length As Long
flags As Long
ShowCmd As Long
ptMinPosition As POINTAPI
ptMaxPosition As POINTAPI
rcNormalPosition As RECT

End Type

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal
lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA"
(ByVal hwnd As Long, ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias
"GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal
wCmd As Long) As Long

Private Const GW_HWNDNEXT = 2
Private Declare Function SetWindowPlacement _
Lib "user32" (ByVal hwnd As Long, _
lpwndpl As WINDOWPLACEMENT) As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As
Long) As Long
Private Declare Function BringWindowToTop Lib "user32" (ByVal hwnd As Long)
As Long
Private Declare Function GetWindowPlacement _
Lib "user32" (ByVal hwnd As Long, _
lpwndpl As WINDOWPLACEMENT) As Long

Public Sub RestoreWindow(sWindowTitle As String)

Dim hWndCtlApp As Long
Dim currWinP As WINDOWPLACEMENT
Dim strPath As String

On Error Resume Next

hWndCtlApp = FindWindow(vbNullString, sWindowTitle)

If hWndCtlApp Then
currWinP.Length = Len(currWinP)

If GetWindowPlacement(hWndCtlApp, currWinP) > 0 Then
If currWinP.ShowCmd = SW_SHOWMINIMIZED Then
'minimized, so restore
currWinP.Length = Len(currWinP)
currWinP.flags = 0&
currWinP.ShowCmd = 3
SetWindowPlacement hWndCtlApp, currWinP
SetForegroundWindow hWndCtlApp
BringWindowToTop hWndCtlApp
Else
'on screen, so assure visible
SetForegroundWindow hWndCtlApp
BringWindowToTop hWndCtlApp
End If
End If
End If

End Sub

Public Function CheckAppRunning(strName As String) As Boolean

On Error Resume Next

'Check for previous existance of program, If running show existing
program.
strPrompt = "The " & App.EXEName & " Is Already Running!" & vbCrLf &
vbCrLf & "The Program Will Attempt To Show App!"
SingleButtonMsg strPrompt, frmLoad.hwnd, 5

RestoreWindow strName

Exit Function

End Function

Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal
sCaption As String) As Boolean
Dim lhWndP As Long
Dim sStr As String
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
GetWindowText lhWndP, sStr, Len(sStr)
sStr = Left$(sStr, Len(sStr) - 1)
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function

Public Sub FindWindowHandle(strName As String)

Dim lhWndP As Long
Dim sMyName As String

If GetHandleFromPartialCaption(lhWndP, strName) = True Then
sMyName = GetWindowName(lhWndP)

If sMyName > "" Then CheckAppRunning sMyName
Else
End If

End Sub

Private Function GetWindowName(ByVal hWindow As Long) As String
Dim strTitle As String * 80
Dim lngLength As Long
lngLength = GetWindowText(hWindow, strTitle, Len(strTitle))
If lngLength Then
GetWindowName = strTitle
Else
GetWindowName = ""
End If
End Function


From: David Youngblood on
"Norm" <NormF4(a)spoof.com> wrote...
> Hi,
> I have an app that runs in the system tray and you click on the icon to
> use functions within the app. Occasionally I have noticed that for some
> reason the app is running but no icon is showing in the system tray, which
> means you cannot access the app.

Do you have the "Hide inactive icons" checked in the Taskbar and Start Menu
properties? I always uncheck this on my own machines. With it checked, as I
recall, there will be some form of button next to the tray to show the
hidden icons.

David



From: duke on
On Apr 21, 9:40 pm, "Norm" <Nor...(a)spoof.com> wrote:
> Hi,
> I have an app that runs in the system tray and you click on the icon to use
> functions within the app. Occasionally I have noticed that for some reason
> the app is running but no icon is showing in the system tray, which means
> you cannot access the app.
>
> When I start a new instance of the app it tells me that the app is already
> running and then shuts down the new instance. I have tried the following
> code, but since the app is only running in the system tray I cannot show the
> app.
>
> Is there a better way to do this so that I can get the apps icon to appear
> in the system tray?
>
> Thanks,
> Norm
>
> Code:
>
> Watch for Line Wrap
>
> I call FindWindowHandle which will get the hwnd form a partial Window Title
> and then once I have the hwnd I can get the correct and full window title
> and try to show that, but it does not show anything since the app is running
> in the system tray.
>
> Option Explicit
>
> Public Type POINTAPI
>         x As Long
>         y As Long
> End Type
>
> Private Type WINDOWPLACEMENT
>
>     Length As Long
>     flags As Long
>     ShowCmd As Long
>     ptMinPosition As POINTAPI
>     ptMaxPosition As POINTAPI
>     rcNormalPosition As RECT
>
> End Type
>
> Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal
> lpClassName As String, _
> ByVal lpWindowName As String) As Long
> Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA"
> (ByVal hwnd As Long, ByVal lpString As String, _
> ByVal cch As Long) As Long
> Private Declare Function GetWindowTextLength Lib "user32" Alias
> "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
> Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal
> wCmd As Long) As Long
>
> Private Const GW_HWNDNEXT = 2
> Private Declare Function SetWindowPlacement _
>                 Lib "user32" (ByVal hwnd As Long, _
>                               lpwndpl As WINDOWPLACEMENT) As Long
> Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As
> Long) As Long
> Private Declare Function BringWindowToTop Lib "user32" (ByVal hwnd As Long)
> As Long
> Private Declare Function GetWindowPlacement _
>                 Lib "user32" (ByVal hwnd As Long, _
>                               lpwndpl As WINDOWPLACEMENT) As Long
>
> Public Sub RestoreWindow(sWindowTitle As String)
>
> Dim hWndCtlApp As Long
> Dim currWinP   As WINDOWPLACEMENT
> Dim strPath As String
>
>     On Error Resume Next
>
>     hWndCtlApp = FindWindow(vbNullString, sWindowTitle)
>
>     If hWndCtlApp Then
>         currWinP.Length = Len(currWinP)
>
>         If GetWindowPlacement(hWndCtlApp, currWinP) > 0 Then
>             If currWinP.ShowCmd = SW_SHOWMINIMIZED Then
>                 'minimized, so restore
>                 currWinP.Length = Len(currWinP)
>                 currWinP.flags = 0&
>                 currWinP.ShowCmd = 3
>                 SetWindowPlacement hWndCtlApp, currWinP
>                 SetForegroundWindow hWndCtlApp
>                 BringWindowToTop hWndCtlApp
>             Else
>                 'on screen, so assure visible
>                 SetForegroundWindow hWndCtlApp
>                 BringWindowToTop hWndCtlApp
>             End If
>         End If
>     End If
>
> End Sub
>
> Public Function CheckAppRunning(strName As String) As Boolean
>
>     On Error Resume Next
>
>     'Check for previous existance of program, If running show existing
> program.
>     strPrompt = "The " & App.EXEName & " Is Already Running!" & vbCrLf &
> vbCrLf & "The Program Will Attempt To Show App!"
>     SingleButtonMsg strPrompt, frmLoad.hwnd, 5
>
>     RestoreWindow strName
>
>     Exit Function
>
> End Function
>
> Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal
> sCaption As String) As Boolean
> Dim lhWndP As Long
> Dim sStr As String
>     GetHandleFromPartialCaption = False
>     lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
>     Do While lhWndP <> 0
>         sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
>         GetWindowText lhWndP, sStr, Len(sStr)
>         sStr = Left$(sStr, Len(sStr) - 1)
>         If InStr(1, sStr, sCaption) > 0 Then
>             GetHandleFromPartialCaption = True
>             lWnd = lhWndP
>             Exit Do
>         End If
>         lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
>     Loop
> End Function
>
> Public Sub FindWindowHandle(strName As String)
>
> Dim lhWndP As Long
> Dim sMyName As String
>
>     If GetHandleFromPartialCaption(lhWndP, strName) = True Then
>         sMyName = GetWindowName(lhWndP)
>
>         If sMyName > "" Then CheckAppRunning sMyName
>     Else
>     End If
>
> End Sub
>
> Private Function GetWindowName(ByVal hWindow As Long) As String
>     Dim strTitle As String * 80
>     Dim lngLength As Long
>     lngLength = GetWindowText(hWindow, strTitle, Len(strTitle))
>     If lngLength Then
>       GetWindowName = strTitle
>     Else
>       GetWindowName = ""
>     End If
> End Function

I also have written a similar program that should "Always Show" in the
system tray and have noticed that occasionally it is not visible with
similar results due to my program checking "Previous Instance"
property.

I am sorry I have not yet found a solution to the problem, but in my
case it seems to be related to the latest version of "Avast" anti-
virus software which I noticed will NOT allow any program to be loaded
prior to avast being completely up and running when I turn on my
computer.
My program is loaded automatically using the System Registry
entry ....... Windows \ CurrentVersion \ Run \ .
I have managed to minimize the occurrence of the problem by
"Hibernating" my computer as opposed to "Turn Off" when shutting down
Windows XP.

I will continue to monitor your post for a more comprehensive
solution.

Duke
From: Nobody on
In one case I had, a service was starting my app when a new user logs in,
but it started it too soon before the task bar was created and the call to
Shell_NotifyIcon() fails. In which case, Err.LastDllError returns
E_FILE_NOT_FOUND. The solution was to try again after Sleep(100) with a
timeout of 10 seconds. Here is a code fragment:

ret = 0
t = Timer
Do While ret = 0 And Abs(Timer - t) < 10
ret = Shell_NotifyIcon(NIM_ADD, NID)
If ret = 0 Then
'MsgBox "ShellTrayAdd: Shell_NotifyIcon failed, LastDllError = "
& Err.LastDllError
End If
Sleep 100
Loop
'MsgBox "ShellTrayAdd: Time taken to add the icon: " & Abs(Timer - t) &
vbCrLf & "LastDllError = " & Err.LastDllError




From: Karl E. Peterson on
Norm wrote:
> I have an app that runs in the system tray and you click on the icon to use
> functions within the app. Occasionally I have noticed that for some reason
> the app is running but no icon is showing in the system tray, which means you
> cannot access the app.

Presumably, you're putting it there properly, using subclassing to
monitor window messages, right? If so, you also need to watch for this
one:

' Registered message sent when Explorer (re)creates taskbar
Private Const TaskbarCreatedString As String = "TaskbarCreated"

' Determine value for "new taskbar" message.
m_msgNewTaskbar = RegisterWindowMessage(TaskbarCreatedString)

When you get it, just recreate your taskbar icon with another call to
ShellNotifyIcon.

> When I start a new instance of the app it tells me that the app is already
> running and then shuts down the new instance. I have tried the following
> code, but since the app is only running in the system tray I cannot show the
> app.
>
> Is there a better way to do this so that I can get the apps icon to appear in
> the system tray?

IF the disappearance is not related to Windows recreating the taskbar,
you'll have to send a message to the previous instance when it's found,
and tell it it needs to recreate its notification icon. I'm betting
the first trick will do it, though.

--
..NET: It's About Trust!
http://vfred.mvps.org