|
|
Comments and Discussions
|
|
 |

|
Unfortunately this this class it won't work on w7. More, the visual scan method it will take a minute to scan the tray rect, if Aero is enabled...due to a slow call to GetPixel() on desktop's hwnd.
And here it's a fix for the visual scan technique. We drop GetPixel() and will capture the tray icon rect as an CImage and perform the visual scan on that.
please include hist 2 files: ScreenImage.h
#pragma once
#include <atlimage.h>
class CScreenImage : public CImage
{
public:
BOOL CaptureRect(const CRect& rect) throw();
BOOL CaptureScreen() throw();
BOOL CaptureWindow(HWND hWnd) throw();
};
ScreenImage.cpp
#include "StdAfx.h"
#include "ScreenImage.h"
BOOL CScreenImage::CaptureRect(const CRect& rect)
{
CImage::Destroy();
HDC hDCScreen = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
HDC hDCMem = ::CreateCompatibleDC(hDCScreen);
HBITMAP hBitmap =
::CreateCompatibleBitmap(hDCScreen, rect.Width(), rect.Height());
HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);
DWORD dwRop = SRCCOPY | CAPTUREBLT;
BOOL bRet = ::BitBlt(hDCMem, 0, 0, rect.Width(), rect.Height(),
hDCScreen,
rect.left, rect.top, dwRop);
Attach(hBitmap);
::SelectObject(hDCMem, hBmpOld);
::DeleteDC(hDCMem);
::DeleteDC(hDCScreen);
return bRet;
}
BOOL CScreenImage::CaptureScreen()
{
CRect rect(0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN));
return CaptureRect(rect);
}
BOOL CScreenImage::CaptureWindow(HWND hWnd)
{
BOOL bRet = FALSE;
if(::IsWindow(hWnd))
{
CRect rect;
::GetWindowRect(hWnd, rect);
bRet = CaptureRect(rect);
}
return bRet;
}
then in
BOOL CTrayIconPosition::FindOutPositionOfIcon(HICON icon)
capture the image from tray's rect:
m_image.CaptureRect(m_rtRectangleOfTheTray);
and modify your code like this:
m_image.CaptureRect(m_rtRectangleOfTheTray);
for(int iy = m_rtRectangleOfTheTray.Height()-3; iy > 1; iy--)
{
int iNoOfPixelsInLine=0;
for(int ix=0;ix<m_rtRectangleOfTheTray.Width();ix++)
{
COLORREF crPixel = m_image.GetPixel( ix, iy);
COLORREF crPixel2 = m_image.GetPixel( ix, iy-2);
COLORREF crPixel3 = m_image.GetPixel( ix, iy+2);
and here:
m_ptPosition.x = m_rtRectangleOfTheTray.left + ix-1;
m_ptPosition.y = m_rtRectangleOfTheTray.top +iy-6;
where:
CScreenImage m_image;
et voila, the tray rect it's working fine with aero.
At the end I found that after
Shell_NotifyIcon(NIM_MODIFY, &nid);
we must add a Sleep(100) to let the shell paint the black icon; otherwise we may not capture the black icon.
modified 9-Mar-12 1:48am.
|
|
|
|

|
Error 1 error C3867: 'CBalloonHelp::KeyboardHookProc': function call missing argument list; use '&CBalloonHelp::KeyboardHookProc' to create a pointer to member c:\downloads\ctrayiconposition_src\balloonhelp.cpp 205
Error 2 error C3867: 'CBalloonHelp::MouseHookProc': function call missing argument list; use '&CBalloonHelp::MouseHookProc' to create a pointer to member c:\downloads\ctrayiconposition_src\balloonhelp.cpp 206
Error 3 error C3867: 'CBalloonHelp::CallWndRetProc': function call missing argument list; use '&CBalloonHelp::CallWndRetProc' to create a pointer to member c:\downloads\ctrayiconposition_src\balloonhelp.cpp 207
Error 4 error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CBalloonHelp::* )(CPoint)' to 'LRESULT (__thiscall CWnd::* )(CPoint)' c:\downloads\ctrayiconposition_src\balloonhelp.cpp 1085
Any ideas?
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein
|
|
|
|

|
I know this is several years too late, but for future reference and as a general comment, why not do what the error messages tell you to?
For errors 1-3 change the signature of the calls
In the case of error 4, change the return value from UINT to LRESULT
--
http://www.coruscant.co.uk/
|
|
|
|

|
Just change the statement
KeyboardHookProc
MouseHookProc
CallWndRetProc
to
&CBalloonHelp::KeyboardHookProc
&CBalloonHelp::MouseHookProc
&CBalloonHelp::CallWndRetProc
World is vivid!
|
|
|
|
|

|
how to delete the trayicon started by another app.
I only have the Trayicon App's HWND, and i do not know its uid and callback function ect...
can anyone help me for deleting the trayicon by using my own App.? i appreciate for
if it is deleted, how to restore the trayicon just being deleted
I know the MSN plug-in can hide the trayicon and the windows of the MSN.
It really convenience that officer can use this to hide the MSN when the manager coming when they're using MSN to contact with friends.(because the manager thought MSN was a waste of working time)
I thought [ShellRegisterCallbacks] could do this.
Using this callback function can forward the [Shell_NotifyIcon] function to a custom shell.
But this way can only work when the MSN runs after the app, I don't know how to do this when the MSN has already run.
hi
|
|
|
|
|

|
I suspect you can. You need just to pass a valid HWND of window that created an icon and the icon id (so this class could be modified to do the trick).
Cheers!
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
Hi,
I am facing one problem: In my application I want to delete my printer Queue document. I am able to delete successfully. \
Now my problem is, the system Tray Icon's tool tip text is not updating the status. it is showing some document is pending in the printer queue.
So I am planning to delete/refresh the printer Icon from the system tray, if any one could help in this then it will be great!...
My mail ID Sebastin_saji@hotmail.com
T.Sebastin.T
|
|
|
|
|

|
yeah, any .net language would be great... Have u tried yet Peter?
All your source are belong to us!
|
|
|
|

|
Some months ago I had ported about 80% of the code to C# (using both managed and p/invoke calls). Things came up and so I never got around to finishing it. I will see what I can do and post and article on it sometime in the future.
|
|
|
|

|
Hello,
First, excuse my bad english (it's not my native language, I'm French).
Then, I'm a studient and I have to create a programm which could hide/unhide any icons in the systray (even extern processes' icons) in VB or in C/C++. Do you know a way to do it?
|
|
|
|

|
:(How to enumerate the icons in the Systray???And How to Get the programe who founds the button in systray? for instance,sound Icon and its button,who founds them??? how to get?
|
|
|
|

|
I can suggest one more approach (not perfect, but worth considering, I think).
Having found the tray window you can send WM_MOUSEMOVE to it with different coordinates trying to guess the icon location. As soon the message is forwarded to your application (wrapped in the message specified when calling Shell_NotifyIcon) you have found it.
Regards,
Sergei.
|
|
|
|
|

|
Oops! Sorry, somehow I have missed that part.
|
|
|
|

|
Thanks to the article,I acquired some knowledges from this.but I have a problem:how to get the tip of the icon in the system tray, and how to get the index of the certain icon in the system tray?
|
|
|
|

|
if the taskbar is hided the arrow of the balloontip appears outside screen, and it should call the taskbar up, like any normal infotips displayed in the taskbar (eg. see how the XP SP2 security warning does). This ballon instead points to the outside of the screen and it's not painted entirely.
otherwise it's a great control.
|
|
|
|

|
I would like to force my tray icon to be always the first in tray.
How can I achieve that ?
|
|
|
|

|
you can modify a direct traking metchod to check if your icon is the first in the toolbar and when it's not - just remove it and then add again - It will land at the first position.
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
Sounds like a race condition if 2 apps starts doing this
- thomasa88
|
|
|
|

|
Does anyone know if there is an official mechanism (or have unofficial ideas;)) to keep a tray icon active so that Windows XP does not "hide" the inactive icon? I assume that by updating the icon periodically, I can keep it "active", but that seems inefficient.
Thanks,
Dave
|
|
|
|

|
If you use a custom dpi in your display settings, say 120 then the code will always fail because windows will scale the icon in the tray area.
|
|
|
|

|
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.
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
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
cButtons = SendMessage(hWndTray, TB_BUTTONCOUNT, ByVal 0&, ByVal 0&)
On Error 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
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
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.
Hope that helps.
Regards
Neal
|
|
|
|
|

|
VirtuaWin uses an icon with a lot of black,
this is sometimes seen as the icon we're looking for!
|
|
|
|

|
I recommend to change a bit code that detects an icon. Now code serches only few lines and test if it's black or near black. Adding more lines to search should help in this case.
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
CheckIfColorIsBlackOrNearBlack could be implemented like this:
BOOL CTrayIconPosition::CheckIfColorIsBlackOrNearBlack(COLORREF crColor)
{
return !(((DWORD)crColor)&0xFCFCFC);
}
and make it inline. code will become mutch faster (well not really a problem here)
or fastest would be to use it as define
#define CheckIfColorIsBlackOrNearBlack(crColor) (!(((DWORD)crColor)&0xFCFCFC))
Or a bit slower
BOOL CTrayIconPosition::CheckIfColorIsBlackOrNearBlack(COLORREF crColor)
{
return (GetRValue(crColor)<4) && (GetGValue(crColor)<4) && (GetBValue(crColor)<4);
}
BTW: nice idea to solve the problem!
What do you think of using an icon with a white border (2pix for 32*32 icon) and calculate the exact rectangle of the icon?
Harald
|
|
|
|
|

|
Add this:
TrayIconPosition.h
CRect m_rcLastTrayPos
TrayIconPosition.cpp
GetTrayIconPosition(CPoint &point, Precision prPrec)
{
...
if(m_rcLastTrayPos!=m_rtRectangleOfTheTray)
bUpdateRequired=1;
if(bUpdateRequired)
{
... m_rcLastTrayPos = m_rtRectangleOfTheTray;
|
|
|
|
|

|
re hello,
I have some mistake with my application. In the OnInitDialog function i do that( i have include CBalloonHelp):
NOTIFYICONDATA nid;
nid.cbSize = sizeof(nid);
nid.hWnd = m_hWnd;
nid.uID = 1;
nid.uFlags = NIF_ICON|NIF_TIP;
// strncpy(nid.szTip, "Our icon in tray :-D", 64);
// nid.hIcon = AfxGetApp()->LoadIcon(IDR_ICON2);
Shell_NotifyIcon(NIM_ADD, &nid);
//let's initialize tray icon position tracking
//second argument it's ID of icon (nid.uID)
m_tipPosition.InitializePositionTracking(m_hWnd,1);
// Add "About..." menu item to system menu.
TraySetIcon(IDR_ICON2);
sprintf(status,"Applicom = %d .Twincat = %d",Appli.GetStatusUnitel(),Appli.GetStatusTwin());
TraySetToolTip(status);
TraySetMenu(IDR_MENU1);
TrayShow(); // Show the tray icon
ShowWindow(SW_HIDE); // Hide the window
But when i call GetTrayIconPosition in CTrayIconPosition, it load a black icon. After what i refresh my icone in the OnTimer() like that:
sprintf(status,"Applicom = %s Twincat = %s",mot,mot2);
TraySetToolTip(status);
//TraySetMenu(IDR_MENU1);
TrayUpdate();
Finaly, my problem is the menu is not attach to my icon and i have to restart my PC because Windows can't killed the thread.
Have you some ideas.
Thanks by advance.
|
|
|
|

|
re
it is like that:
sprintf(status,"Applicom = %s Twincat = %s",mot,mot2);
TraySetToolTip(status);
TraySetMenu(IDR_MENU1);
TrayUpdate();
|
|
|
|
|

|
As far I know - balloon can be constructed with TOPMOST attribute - it should help
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
ok, thanks that's work with TOPMOST.
One more time great job
|
|
|
|

|
Thanks Irek! I was looking for such code for a long time... Well done Przemek
|
|
|
|

|
This "Tray Icon" doesn't position itself correctly when the taskbar is on the left or on the right of the desktop. And the pointer in such situation looks real ugly.
Regards,
Vitaly Tomilov
Ultimate all-in-one XP-Style UI multiplatform solution: Tooltips, XP Menus, Hyperlinks, Drawing Graphics and formatted documents, plus powerful binary resource reuse. All Free 100% on www.tooltips.net. It can be used in VC++, C#, Java+, VB, Delphi, C++ Builder, as well as in any COM-compatible platform.
|
|
|
|

|
That's not true. Position is beign calculated correctly.
This is rater bug in CBalloonHelp class that is not able to display balloon with such anchor points in a nice way.
Please relly on coordinates that application returns rather than the outlook of third-party-created balloon.
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
- The position is not calculated correctly, as the balloon won't overlap the taskbar ever!
- I relied on your demo project, in which, if I use my taskbar on the left or right side of the desktop the balloon's pointer looks horrible!
- Did you ever try your example on a multimonitor system?
Regards,
Vitaly
Professional tooltips for all development platforms Free on www.Tooltips.NET
|
|
|
|

|
I think I have to make some things clear.
First of all this article describes CTrayIconPosition class and have nothing to do with CBalloonHelp class by Shog.
The most important data that is being calculated by demo application are X/Y coordinates of tray icon. While creating demo application I had to decide how to display those coordinates - at first I was thinking about simple MessageBox with such kind of message: "Icon found! Coordinates X[xxx] Y[yyy]."
But since I use balloon class in my applications I thought that it would be a good idea to not only show the raw coordinates but also display example of usage of this class.
So while testing this class - please compare COORDINATES given in result with position of your tray icon. Balloon is only example of use of this coordinates.
As you suggest balloon looks ugly when task bar is in left or right part of the screen - that's true. But it has nothing to do with CTrayIconPosition class described here.
I think that far better place to point this bug is CBalloonHelp discussion forum (link on the beginning of article).
About multi-monitors:
CTrayIconPosition was not checked under multi-monitor environment. But I don't predict any problems - if I'm wrong - let me know about that.
I hope this will clarify some things and there will be no more misunderstandings.
Best regards,
Irek
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
What about sending WM_MOUSEMOVE directly to that window with client coordinates that jump by 16 pixels across the area? Then you have no bitmap scanning or anything like that, and you just catch your WM_MOUSEMOVE being sent in your code. Probably a little faster.
-Ian
|
|
|
|
|

|
Well
I spent some time investigting this possibility.
Since it seems to work - it has one serious disadventage.
I have few applications in my tray and one of them started to dispaly a tool tip while recieving WM_MOUSEMOVE mesage. I'm afraid that is not acceptable.
I'm going to spend more time on this matter but seems to me sending fake messages could lead some tray applications to behave strangely.
Check out my software at: http://www.ireksoftware.com
|
|
|
|

|
Irek Zielinski wrote:
I have few applications in my tray and one of them started to dispaly a tool tip while recieving WM_MOUSEMOVE mesage. I'm afraid that is not acceptable.
Yea, that's no good. Do you send more than one mousemove to the same icon area?
|
|
|
|

|
Actualy I was trying few ways to send this WM_MOUSEMOVE message. I'm afraid if I was able to find one application that actualy cares about WM_MOUSEMOVE - there could be more such applications installed on PCs of my users. The problem is that there is no way to guess if fake messages you send will be ignored by tray applications or not.
But thanks for poiting this idea - it could prove usefull someday!
Check out my software at: http://www.ireksoftware.com
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Ever wanted to know position of your tray icon? Windows supplies no API for that. This class is a compact solution that works.
| Type | Article |
| Licence | CPOL |
| First Posted | 20 Feb 2003 |
| Views | 172,220 |
| Downloads | 4,455 |
| Bookmarked | 82 times |
|
|