Hmmm... my display settings are actually "big fonts" (120 dpi) and it seems to work perfect. Scaling the icon is not a problem for this code since plain black icon scaled to be larger will also be a black icon.
That was the only reason i could come up with for it not working on my Win XP system. the only other variable is that I have the task bar at the top of the screen. Anyway I've worked out a way to do the same, without any image processing, See below.
The codes is in vb6 but you should be able to easily convert it. The call to GethWndTray (which gets the tray's toolbar control has been ommited for compactness.
Private Type TrayData hWnd As Long ID As Long End Type
Public Function GetSystemTrayItemRect(ByVal hWnd As Long, ByVal ID As Long) As RECT Dim hWndTray As Long Dim hProc As Long Dim pid As Long Dim vaPtr As Long Dim ret As Long Dim tbut As TBBUTTON Dim cButtons As Long Dim td As TrayData Dim i As Long Dim rc As RECT
hWndTray = GethWndTray If hWndTray = 0 Then Exit Function
Call GetWindowThreadProcessId(hWndTray, pid) If pid = 0 Then Exit Function
hProc = OpenProcess(PROCESS_VM, 0, pid) If hProc = 0 Then Exit Function
vaPtr = VirtualAllocEx(hProc, ByVal 0&, Len(tbut), MEM_COMMIT, PAGE_READWRITE) If vaPtr = 0 Then GoTo cleanup
For i = 0 To cButtons - 1 Call SendMessage(hWndTray, TB_GETBUTTON, i, ByVal vaPtr) Call ReadProcessMemory(hProc, ByVal vaPtr, tbut, Len(tbut), ret)
If Not tbut.dwData = 0 Then Call ReadProcessMemory(hProc, ByVal tbut.dwData, td, Len(td), ret) If hWnd = td.hWnd Then If ID = td.ID Then Call SendMessage(hWndTray, TB_GETITEMRECT, i, ByVal vaPtr) Call ReadProcessMemory(hProc, ByVal vaPtr, rc, Len(rc), ret) Exit For End If End If End If Next Call MapWindowPoints(hWndTray, 0&, rc, 2) GetSystemTrayItemRect = rc
cleanup: If hProc Then If vaPtr Then Call VirtualFreeEx(hProc, ByVal vaPtr, 0&, MEM_RELEASE) End If End If If hProc Then CloseHandle (hProc) End Function
Hi I have ported VB example you provided to C++ and it looks promising. The problem is that all you can retrive with this example it's rectangle of each button in a tray (cool!) and TBBUTTON structure. But TBBUTTON seems to be not enought to determinate witch one of the buttons belongs to our application. Especialy there is no HWND member and button ID member seems to have different values that this ID we specify while adding icon to the tray.
in VB code there is a piece of code:
If hWnd = td.hWnd Then
If ID = td.ID Then
but in C++ definition of TBBUTTON of this structure there are no such members. Anyone hve any idea how to solve it? Best regars, Irek
Copy the first 8 bytes of the dwData member of the TBBUTTON, using the ReadProcessMemory API as you did to get the TBBUTTON struct. The first 4 bytes is the hWnd the button belongs to. The second 4 bytes is the NOTIFYICONDATA.iUD.
Then using the index of the button you can then get the it's rect by calling TB_GETITEMRECT, again ReadProcessMemory is required. As seen in my earlier post.
There appear's to be alot more info in dwData but I just use the first 8.