As you might imagine, I have several desktop shortcuts. I’ve made no secret of my hatred of all things pointy and clicky. I guess I just long for the old DOS days.
My desktop shortcuts are far from unruly. I rarely have a problem remebering one when I need it. But I do have a problem knowing which are free when I want to create a new one. I know that Adobe Acrobat is Ctrl+Alt+B, but I don’t know that U is still unused.
I can’t decide if I should assign letters based on the name of the software or its function, so I have a mishmash of both plus some that are assigned based on the predominant sound in the name rather than the first letter. That’s just a little disclaimer to prevent the comments like “Why would Adobe Acrobat be Ctrl+Alt+B?”. If you assume they make no sense, it will be a lot easier for both of us.
I started using the FileSystemObject to loop through all the files in the Desktop folder. I new that the File object had a Type property which I could compare to the string “Shortcut” to start limiting the files. I suppose I could just as easily loop through the files using the Dir function and a *.lnk filter, but I had alterior motives. I thought, incorrectly, that if the File had a Type property to help me identify shortcuts, it would have some other helpful properties for me to get the hotkey. If it does, I sure couldn’t find them.
“No problem”, I say to myself, “I’ll just use an API”. I’m not very good at finding the appropriate API for a couple of reasons: First, I’m a neophyte when it comes to APIs so I don’t have a good base of knowledge; Second, I shun MSDN whenever possible because it makes me use Internet Explorer to be able to use the left side navigation. After searching high and low, I fired up IE and searched MSDN. I really couldn’t find anything.
The story of my search is pretty boring, so I’ll cut to the chase. I found the Shell32 type library which had some promising object names. I went to the VBE, set a reference, and started Object Browsing (F2). It looks like I have everything I need, but I’m struggling to make sense of the Hotkey property of the ShellLinkObject object. I only use Control+Alt+Letter on my desktop, but I set up a couple of others for testing purposes:
Key Combo | A | B |
Ctrl+Shift | 833 | 834 |
Ctrl+Alt | 1601 | 1602 |
Shift+Alt | 1345 | 1346 |
According to MSDN, Shift=1, Ctrl=2, Alt=4, Extended=8. Well, I thought I was on to something when I only had Ctrl+Alt hotkeys. They all start with 16, so if 1 is a place holder and 6 is the only number that will evaluate bitwise with 2 and 4, then I must be golden. Then I did the other two combinations and threw my theory out the window. Shift+Alt should have started with 15 and Ctrl+Shift should have started with 13.
Here’s my inelegant code. If someone wants to enlighten me about the Hotkey property, that would be great.
Dim oShell As Shell32.Shell
Dim oFldr As Shell32.Folder
Dim oFItm As Shell32.FolderItem
Dim oLnk As Shell32.ShellLinkObject
Dim i As Long
Const sCS As String = “Ctrl+Shift+”
Const sCA As String = “Ctrl+Alt+”
Const sSA As String = “Shift+Alt+”
Set oShell = New Shell32.Shell
Set oFldr = oShell.NameSpace(ssfDESKTOP)
For Each oFItm In oFldr.Items
If oFItm.IsLink Then
Set oLnk = oFItm.GetLink
If oLnk.Hotkey > 1599 Then
i = i + 1
Sheet1.Cells(i, 1).Value = oFItm.Name
Sheet1.Cells(i, 2).Value = oLnk.Path
Sheet1.Cells(i, 3).Value = sCA & Chr(oLnk.Hotkey – 1599 + 63)
ElseIf oLnk.Hotkey > 1344 Then
i = i + 1
Sheet1.Cells(i, 1).Value = oFItm.Name
Sheet1.Cells(i, 2).Value = oLnk.Path
Sheet1.Cells(i, 3).Value = sSA & Chr(oLnk.Hotkey – 1344 + 63)
ElseIf oLnk.Hotkey > 832 Then
i = i + 1
Sheet1.Cells(i, 1).Value = oFItm.Name
Sheet1.Cells(i, 2).Value = oLnk.Path
Sheet1.Cells(i, 3).Value = sCS & Chr(oLnk.Hotkey – 832 + 63)
End If
End If
Next oFItm
End Sub
Don’t forget to set a reference to the Shell32 type library
According to the MSDN article:
“The virtual key code is in the low-order byte, and the modifier flags are in the high-order byte”
Something like this applies:
IIf((oLnk.Hotkey And &H100) = 0, “”, “Shift “) & _
IIf((oLnk.Hotkey And &H200) = 0, “”, “Ctrl “) & _
IIf((oLnk.Hotkey And &H400) = 0, “”, “Alt “) & _
Chr(oLnk.Hotkey And &HFF)
Ding Ding Ding Ding. It makes perfect sense now. Integer = 16 bits = 2 bytes. High order = 256 and above, low order = 128 and below.
More dumb questions: Why do they say Shift=1 instead of Shift = 256 (if they would have said that I would have got it)? Why do you use hex in your comparison instead of (oLnk.Hotkey And 256)?
Thanks, Rob.
From my assembler programming days…
I’ve memorised the bit equivilent for each nibble:
0 = 0000, 1 = 0001, 2 = 0010, 3 = 0011
4 = 0100, 5 = 0101, 6 = 0110, 7 = 0111
8 = 1000, 9 = 1001, A = 1010, B = 1011
C = 1100, D = 1101, E = 1110, F = 1111
So I can work out in my head which bits are set or not given a hexadecimal number.
Yes, I am a geek ;)