Click to See Complete Forum and Search --> : How to always show an icon in system tray?


KNoodles
August 17th, 2004, 06:41 PM
Hi,

How do I customize systray icon behaviour programatically? I'd like to change the standard "Hide when inactive" behaviour to "Always show" in my application. Has anyone done this before? I could do it by refreshing the systray icon on a timer but this is not the right way I guess.

Any help would be appreciated.

KNoodles

dit6a9
August 17th, 2004, 11:04 PM
Here you can find a lot of information about Windows Shell:

Shell Programmer's Guide (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_intro.asp)

In particular you'll find this very useful:

The Taskbar (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_int/shell_int_programming/taskbar.asp)

Examples are a very good place to start.

KNoodles
August 17th, 2004, 11:20 PM
Thanks for your reply...

I've already got a perfectly working application that minimises into the systray. Just looking for a flag/API call/option that will allow me to programatically set the systray icon behaviour to "Always Show". I've searched high and low. Cant find anything like this anywhere.

Thanks

sbubis
August 18th, 2004, 12:31 AM
According to MSDN:
Taskbar Display Options
The taskbar supports two display options: Auto Hide and Always On Top. To set these options, the user must open the taskbar shortcut menu, click Properties, and select or clear the Auto Hide check box or the Always On Top check box. There is no way to set these options programmatically. To retrieve the state of these display options, use the ABM_GETSTATE message. If you would like to be notified when the state of these display options changes, process the ABN_STATECHANGE notification message in your window procedure.

KNoodles
August 18th, 2004, 12:47 AM
Does this apply to the system tray icons as well because I dont want to hide/unhide the whole taskbar? I only want to make sure a system tray icon stays visible all the time.

Thanks

sbubis
August 18th, 2004, 12:52 AM
Sorry, I don't know

wey97
August 19th, 2004, 10:38 AM
Calling:

BOOL Shell_NotifyIcon(DWORD dwMessage,
PNOTIFYICONDATA lpdata
);

passing NIM_ADD as dwMessage will keep an icon in the system tray until you call Shell_NotifyIcon again passing NIM_DELETE as the first parameter.

Look into it and if you can't figure it out I'll post a sample.

KNoodles
August 19th, 2004, 11:02 PM
I've already got all the NIM_ADD stuff working. Need to make sure my icon doesnt hide itself when my app stays inactive for a bit. Can this be done programatically? Does anyone understand my question because all the answers so far have been off topic?

KNoodles

wey97
August 23rd, 2004, 07:19 AM
I think you may be confusing the behavior of your application with a built in feature of Windows XP if that's what OS you're on. If you haven't noticed, it should be affecting other application icons too. I don't know of any other OS that acts that way except maybe Windows Server 2003 which I haven't used.

That's a feature that has nothing to do with any application. The only way to set the feature is to right click the Taskbar or do it programmatically by setting a registry key http://www.winguides.com/registry/display.php/918/

KNoodles
August 23rd, 2004, 05:50 PM
Hi, beaut...

Thanks for your answer. I mustn't have explained my problem clearly. But that's kind of what I'm after. The reg key in your link applies to the whole windows environment.

User Key: [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer]
Value Name: EnableAutoTray
Data Type: REG_DWORD (DWORD Value)
Value Data: (0 = display inactive icons, 1 = hide inactive icons)

Do you know of a way of doing it app by app?

Link to a similar question (http://www.experts-exchange.com/Programming/Q_20844213.html)

KNoodles

KNoodles
August 29th, 2004, 08:46 PM
- Bump -

RoboTact
September 1st, 2004, 04:25 AM
Maybe periodicall adding or refreshing (changing the icon to the same one, etc.) may help... It it is not, you may try to send user activity messages to the bar determined the position of the icon.

CocoMomoCoco
September 16th, 2004, 04:13 AM
Hi KNoodles,

I also need the same thing: to "Always show" just my icon application even if it is inactive and the "Hide inactive icons" is selected. Manually this can be set like: taskbar->properties->hide inactive icons->customize->my app -> behavior->always show, but I couldn't yet find a way to do this programmatically. Have you found anything?

I assumed being a registry flag, but couldn't find such :(

Thanks,
Viv

CrystalAnnoysMe
April 1st, 2009, 03:28 PM
This thread is ancient but I'm working on doing this in a program and have run into the same wall as everyone else but I think I've gotten a bit further.

Appears windows stores the "Always Hide", "Always Show", "Hide When Inactive" in the following key:

HKEY_Current_User\Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify

In there is a IconStreams (fur currently running programs) and PastIconsStream (name explains what that is). The hard part is each is a huge byte that has the start up path of a app in it along with the switch on how to display. The harder part is it loads this key into memory at startup, all changes you do within the UI are done only to memory, then it rewrites the key on shutdown. Modifying the key ONLY works if you kill the explorer task.

So it appears, without having some direct API call or memory location to this data, the only way to do it is to run your application at least once with the notify icon showing, reboot the machine (to write your app notify info the registry key), start your app back up, search for your application path in it, find the switch, switch it, write it back to the registry, then purposely kill the explorer.exe process and restart the process which will force it to re poll the registry key.

PITA but doable....I have the code almost done, just not sure if it's going to be worth the hassle.

-Allan

CrystalAnnoysMe
April 2nd, 2009, 02:14 PM
Think this will do it. Not fully tested but it will get anyone trying a real good head start.

Friend Function AlwaysShowNotifyIcon(ByVal WhenToShow As Byte) As Boolean
' Searches for a notify icon by application path in the registry and updates the key to always show, always hide, or hide when inactive
' WhenToShow should be 16 (Dec) for always (verified), 17 (dec) for never (I'm guessing on this), and 18 (Dec) for hide when inactive (verified).
' This will return success status. Highly suggest putting a local setting variable in to only run this once per machine....
Dim x As Integer = 0
Dim myHolderString As String
Dim encText As System.Text.UTF8Encoding = New System.Text.UTF8Encoding()
Try
' Get our registry entry
Dim myRegistryKeyAsByte As Byte() = Nothing
Dim myRegistryKeyAsString As String = ""
Try
' Get the registry key
myRegistryKeyAsByte = ReadCURKByte("Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify", "IconStreams", Nothing)
' Convert the bytes to a string of hex values
For x = 0 To UBound(myRegistryKeyAsByte)
myHolderString = DoubleToHex(myRegistryKeyAsByte(x))
Select Case myHolderString.Length
Case 0
myRegistryKeyAsString += "00"
Case 1
myRegistryKeyAsString += "0" + myHolderString
Case 2
myRegistryKeyAsString += myHolderString
End Select
Next
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try

' Get our application path
Dim myTempAppPathAsByte As Byte()
myTempAppPathAsByte = encText.GetBytes(My.Application.Info.DirectoryPath.ToString & "\" & My.Application.Info.AssemblyName)
Dim myAppPathAsByte(UBound(myTempAppPathAsByte) * 2) As Byte
Dim myAppPathAsString As String = ""
Try
' Add in zeros for every other byte like the registry key has
For x = 0 To UBound(myAppPathAsByte)
If x Mod 2 = 0 Then
myAppPathAsByte(x) = myTempAppPathAsByte(CInt(x / 2))
Else
myAppPathAsByte(x) = 0
End If
Next
' Convert the bytes to a string of hex values
For x = 0 To UBound(myAppPathAsByte)
myHolderString = DoubleToHex(myAppPathAsByte(x))
Select Case myHolderString.Length
Case 0
myAppPathAsString += "00"
Case 1
myAppPathAsString += "0" + myHolderString
Case 2
myAppPathAsString += myHolderString
End Select
Next
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try

' Hunt for the application path inside the registry key
Dim myPosition As Long = InStr(myRegistryKeyAsString, myAppPathAsString) - 1

If myPosition > 0 Then
' We found our startup path so make our change to the byte 20 before the start of the path
' I believe this is the right byte to change from manually setting a icon. I exported out the TrayIcon
' key, changed the value, rebooted, and expored it out again and this byte was the only thing to change
myRegistryKeyAsByte(CInt(myPosition / 2 - 20)) = WhenToShow
' Write the modified key back to the registry
WriteCURKByteValue("Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify", "IconStreams", myRegistryKeyAsByte)
' Now crash explorer. Thats right....explorer keeps this information in memory and reads it at startup and writes it at shutdown
' so the only way to actaully change these values is to write to the registry then crash explorer so it can't overwrite what
' we did. It will then poll our information when it starts back up. First look for explorer in memory:
Dim ExplorerProcess As Process = Nothing
For Each p As Process In Process.GetProcesses
If p.ProcessName.ToString = "explorer" Then
ExplorerProcess = p
Exit For
Else
ExplorerProcess = Nothing
End If
Next
' If we found it then we kill it, it will restart itself
If Not ExplorerProcess Is Nothing Then
ExplorerProcess.Kill()
Threading.Thread.Sleep(2000)
End If
Else
Return False
End If

Catch ex As Exception
Debug.WriteLine(ex.Message)
Return False
End Try

End Function

Private Function DoubleToHex(ByVal x As Double) As String
DoubleToHex = ""
Dim lrem As Double
While x > 0
lrem = x - Int(x / 16) * 16
DoubleToHex = Hex(lrem) & DoubleToHex
x = Int(x / 16)
End While
End Function

carl666
April 3rd, 2009, 03:31 AM
I have the code almost done, just not sure if it's going to be worth the hassle.


The code (C) had been posted many times on Google (Groups) archives (Win32 api)
, RPM and so on with internal Shell structures...

CrystalAnnoysMe
April 3rd, 2009, 07:47 AM
You have any links to that? I've been searching for the answer to this for a while and can't find it nor have others been able to find it. This thread was the closest I've found.