From: Norm on 21 Apr 2010 23:40 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 22 Apr 2010 00:34 "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 22 Apr 2010 12:24 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 22 Apr 2010 12:53 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 22 Apr 2010 13:45
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 |