Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Making certain programs' tray icons "always show" programatically

11 views
Skip to first unread message

Josh Miller

unread,
May 10, 2004, 10:25:09 PM5/10/04
to
I was looking for a way to automate the process of picking what
programs "Hide always", "Show always" or "Hide when unused" etc like
you can do manually by right clicking on your taskbar, going into
properties, then clicking the "Customize" button in the Notification
Area. I wrote a program that uses a tray icon and I didn't want the
icon to disappear but couldn't figure out a way to force XP to make my
icon "always show". A did a search but couldn't come up with anything
except someone else looking to do the same:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=mustang-1C4564.02000101092001%40enews.newsguy.com&rnum=1&prev=/groups%3Fq%3DMaking%2Ban%2Bicon%2BSTAY%2Bin%2Bthe%2Bsystem%2Btray%2Bprogramatically%26hl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26selm%3Dmustang-1C4564.02000101092001%2540enews.newsguy.com%26rnum%3D1

Well I figured it out and decided I'd save someone some time should
they ever want to do the same thing. I apologize for the long lines. I
don't have to sit and reformat the lines for 50 spaces across or
whatever it is in here but I'm sure any knowledgable programmer
interested enough in doing this can fix the line breaks.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Option Explicit
Public Const HKCU = &H80000001
Public Const REG_SZ = 1
Public Const REG_EXPAND_SZ = 2
Public Const REG_BINARY = 3
Public Const REG_DWORD = 4

Public Const REG_OPTION_NON_VOLATILE = 0
Public Const REG_CREATED_NEW_KEY = &H1
Public Const REG_OPENED_EXISTING_KEY = &H2

Public Const KEY_QUERY_VALUE = &H1
Public Const KEY_ENUMERATE_SUB_KEYS = &H8
Public Const KEY_NOTIFY = &H10
Public Const READ_CONTROL = &H20000
Public Const STANDARD_RIGHTS_ALL = &H1F0000
Public Const STANDARD_RIGHTS_EXECUTE = (READ_CONTROL)
Public Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
Public Const SYNCHRONIZE = &H100000
Public Const KEY_READ = ((STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or
KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY) And (Not SYNCHRONIZE))
Public Const KEY_SET_VALUE = &H2
Public Const KEY_CREATE_SUB_KEY = &H4
Public Const KEY_CREATE_LINK = &H20
Public Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
Public Const KEY_WRITE = ((STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or
KEY_CREATE_SUB_KEY) And (Not SYNCHRONIZE))
Public Const KEY_ALL_ACCESS = ((STANDARD_RIGHTS_ALL Or KEY_QUERY_VALUE
Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY Or KEY_ENUMERATE_SUB_KEYS Or
KEY_NOTIFY Or KEY_CREATE_LINK) And (Not SYNCHRONIZE))

Public Const ERROR_SUCCESS = 0&
Public Const ERROR_ACCESS_DENIED = 5&
Public Const ERROR_MORE_DATA = 234&
Public Const ERROR_NO_MORE_ITEMS = 259&
Public Const ERROR_BADKEY = 1010&
Public Const ERROR_CANTOPEN = 1011&
Public Const ERROR_CANTREAD = 1012&
Public Const ERROR_REGISTRY_CORRUPT = 1015&

Public Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Boolean
End Type

Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias
"RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal
ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As
Long
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias
"RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String,
ByVal lpReserved As Long, lpType As Long, lpData As Any, dwSize As
Long) As Long
Private Declare Function RegSetValueEx Lib "advapi32.dll" Alias
"RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String,
ByVal dwReserved As Long, ByVal dwType As Long, lpValue As Any, ByVal
dwSize As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As
Long) As Long
Private Declare Function RegCreateKeyEx Lib "advapi32" Alias
"RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal
Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long,
ByVal samDesired As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES,
phkResult As Long, lpdwDisposition As Long) As Long

Public Function ReadReg(hKey As Long, SubKey As String, DataName As
String, DefaultData As Variant) As Variant
Dim hKeyResult As Long, lData As Long, result As Long
Dim DataType As Long, DataSize As Long
Dim sData As String, baData() As Byte

ReadReg = DefaultData
result = RegOpenKeyEx(hKey, SubKey, 0, KEY_QUERY_VALUE, hKeyResult)
If result <> ERROR_SUCCESS Then Exit Function

result = RegQueryValueEx(hKeyResult, DataName, 0&, DataType, ByVal
0, DataSize)
If result <> ERROR_SUCCESS Or DataSize = 0 Then
RegCloseKey hKeyResult
Exit Function
End If
Select Case DataType
Case REG_SZ, REG_EXPAND_SZ
sData = Space(DataSize + 1)
result = RegQueryValueEx(hKeyResult, DataName, 0&, DataType,
ByVal sData, DataSize)
sData = RTrim(StripNulls(sData))
If result = ERROR_SUCCESS And sData <> "" Then ReadReg =
CVar(sData)
Case REG_DWORD
result = RegQueryValueEx(hKeyResult, DataName, 0&, DataType,
lData, 4)
If result = ERROR_SUCCESS Then ReadReg = CVar(lData)
Case REG_BINARY
ReDim baData(DataSize - 1)
result = RegQueryValueEx(hKeyResult, DataName, 0&, DataType,
baData(0), DataSize)
If result = ERROR_SUCCESS Then ReadReg = baData
End Select
RegCloseKey hKeyResult
End Function

Public Function StripNulls(ByVal s As String) As String
Dim i As Integer
StripNulls = s
i = InStr(s, vbNullChar)
If i > 0 Then _
StripNulls = Left(s, i - 1)
End Function

Public Function WriteRegBinaryArray(hKey As Long, SubKey As String,
DataName As String, ba() As Byte) As Long
Dim sa As SECURITY_ATTRIBUTES
Dim hKeyResult As Long, lDisposition As Long, result As Long

sa.nLength = Len(sa)
sa.lpSecurityDescriptor = 0
sa.bInheritHandle = False

result = RegCreateKeyEx(hKey, SubKey, 0, "",
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, _
sa, hKeyResult, lDisposition)

If (result = ERROR_SUCCESS) Or (result = REG_CREATED_NEW_KEY) Or
(result = REG_OPENED_EXISTING_KEY) Then
result = RegSetValueEx(hKeyResult, DataName, 0&, REG_BINARY,
ba(0), UBound(ba) + 1)
RegCloseKey hKeyResult
End If
WriteRegBinaryArray = result
End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Josh Miller 5/04 duh...@hotmail.com
'Below, where you see "Enter tooltip here", you must put either all
'of or just the first few words of (enough to be unique) the
'desired programs' tray icon tooltip. It is CASE SENSITIVE. ie:
"Volume",
'"You have new unopened" (MS Outlook mail notification), etc etc.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Sub Main()
Dim iLoc As Long, sData() As Byte
sData = ReadReg(HKCU,
"Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify",
"IconStreams", "")
iLoc = InStrB(sData, Format("ENTER TOOLTIP HERE", vbUnicode))
sData(iLoc - 9) = 2 '0 is Hide when inactive, 1 is Always Hide, 2 is
Always Show
WriteRegBinaryArray HKCU,
"Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify",
"IconStreams", sData()
End Sub

Karl E. Peterson

unread,
May 11, 2004, 12:23:44 PM5/11/04
to
Josh Miller <duh...@hotmail.com> wrote:
> Well I figured it out and decided I'd save someone some time should
> they ever want to do the same thing.

Very cool. Is it possible to summarize in a few sentences? Something like, "set the
[blah blah] key in the registry to [blah blah]"? Sort of an "Abstract" to the
solution?

> I apologize for the long lines. I
> don't have to sit and reformat the lines for 50 spaces across or
> whatever it is in here but I'm sure any knowledgable programmer
> interested enough in doing this can fix the line breaks.

One "trick" I use when posting code is to first highlight it all in the VB IDE, press
tab to indent, then copy it to the clipboard. That makes linewraps totally obvious
as they're the only ones that begin in column 1.

Thanks... Karl
--
[Microsoft Basic: 1976-2001, RIP]


Rick Rothstein

unread,
May 11, 2004, 1:34:43 PM5/11/04
to
> > I apologize for the long lines. I
> > don't have to sit and reformat the lines for 50 spaces across or
> > whatever it is in here but I'm sure any knowledgable programmer
> > interested enough in doing this can fix the line breaks.
>
> One "trick" I use when posting code is to first highlight it all in
the VB IDE, press
> tab to indent, then copy it to the clipboard. That makes linewraps
totally obvious
> as they're the only ones that begin in column 1.

You don't use Labels (as in the target for an On Error Goto) in your
programs?<g>

Rick - MVP

Karl E. Peterson

unread,
May 11, 2004, 1:41:02 PM5/11/04
to

Only in the *rarest* of circumstances. First off, 98% of my code is error-free, so
there's no need. <bSEg> And, of the remaining 2%, I almost always induce the errors
myself, and tend to prefer the On Error Resume Next flow. In probably ten of the
thousands of routines I keep around, do I use a jump label. And, on the *extremely*
rare occassion when I post one of those, yes, I do manually have to indent that one
line.

Flame on... ;-)

songie D

unread,
May 11, 2004, 3:45:22 PM5/11/04
to
For god's sake. For a start this is unique to XP, so it's probably a bad
idea to code it anyway. Secondly, this is the user's settings, not yours,
and shouldn't be at the mercy of your program to mess around with.
Why are you arrogantly assuming that there's something that makes
your program so much better than all others that you KNOW for a fact
that the user will not want autohide to hide your icon?
Your icon's made available. That's as much as you should provide.


"Josh Miller" <duh...@hotmail.com> wrote in message
news:2e1feb28.0405...@posting.google.com...

Josh Miller

unread,
May 11, 2004, 5:28:20 PM5/11/04
to
I forgot to mention that this change will only take effect after a
reboot or after you kill the explorer process and restart it. If your
application starts on Windows startup, killing the explorer process
and restarting it won't be noticed as much. Otherwise, this is more
something that you want to set install or on the initial run of your
program and suggest a reboot.

Josh Miller

unread,
May 12, 2004, 5:18:11 PM5/12/04
to
"songie D" <son...@D.com> wrote in message news:<OP1p$B5NEH...@tk2msftngp13.phx.gbl>...

> For god's sake. For a start this is unique to XP, so it's probably a bad
> idea to code it anyway. Secondly, this is the user's settings, not yours,
> and shouldn't be at the mercy of your program to mess around with.
> Why are you arrogantly assuming that there's something that makes
> your program so much better than all others that you KNOW for a fact
> that the user will not want autohide to hide your icon?
> Your icon's made available. That's as much as you should provide.

It's just information man. Relax. I'm not saying you or anyone else
has to do this but if someone WANTS to, this is HOW. NGs are about
information exchange. I was looking for a way to do this because this
program happens to be an admin utility that I wrote that sits in the
tray on 500+ machines in the building I administer. I can communicate
with all the machines, send commands to them, query file/folder/user
information, query/modify registry, etc, etc. I use it to give myself
admin privileges and special featuers when I visit their desktops.
The users use it to quickly lock their workstations by single clicking
on the icon when it's sitting in the tray. On XP machines, they have
to click the little arrow to make the unused tray icons show up and
then click my icon to lock the their workstation. Not that big of a
deal but just something I wanted to "fix".

Something else I realised is that there should be a check to make sure
the text is found before modifying and setting the registry value. If
the program hasn't run yet or if this is the first day it has run and
the machine hasn't been rebooted, it won't be in the IconStreams
registry value.

songie D

unread,
May 15, 2004, 7:06:02 AM5/15/04
to
you sound like the sort of "IT-bully" the world doesn't need.

"Josh Miller" <duh...@hotmail.com> wrote in message

news:2e1feb28.04051...@posting.google.com...

0 new messages