Reputation: 352
I have developed a small application, which places an icon in the system tray, and displays a form above it.
When I filled in the TNotifyIconData
structure myself and called the Shell_NotifyIcon
function to add the icon, I could use the TNotifyIconIdentifier
structure to use the Shell_NotifyIconGetRect
function and get the location of the icon, thus displaying the form above it.
I now use the TTrayIcon
component, which is easier to deal with, but now I can not set the TNotifyIconIdentifier
structure correctly to do what I wanted.
I declared the structure on the form as follows:
...
TrayIconForTest: TTrayIcon;
...
public
TrayIconIdentifier: TNotifyIconIdentifier;
...
And I fill it in with the event handler FormCreate
like this:
with TrayIconIdentifier do
begin
cbSize := SizeOf(TNotifyIconIdentifier);
hWnd := Handle;
uID := AllocateHwnd(WindowProc);
GuidItem := GUID_NULL;
end;
Then I wrapped the Shell_NotifyIconGetRect
function like this:
function TTesterForm.GetTrayIconRect(var R: TRect): Boolean;
var
FResult: HRESULT;
begin
FResult := Shell_NotifyIconGetRect(TrayIconIdentifier, R);
if FResult = S_OK then
Result := True
else
begin
MessageBox(0, PWideChar('The system tray icon location could not be found. '+SysErrorMessage(FResult, 0)+'.'), 'Shell_NotifyIconGetRect Error', MB_OK or MB_ICONSTOP);
Result := False;
end;
end;
But when I call the GetTrayIconRect
function, it displays the error.
The problem seems to be with the TNotifyIconIdentifier build, but I did not find what I was doing wrong. I checked the Vcl.ExtCtrls unit, and found no direction.
When I tried to transfer the data from TTrayIcon like this (I saw someone who posted this solution):
with TrayIconIdentifier do
begin
FillChar(TrayIconIdentifier, SizeOf(TrayIconIdentifier), #0);
cbSize := SizeOf(TNotifyIconIdentifier);
hWnd := TrayIconForTest.Data.Wnd;
uID := TrayIconForTest.Data.uID;
GuidItem := GUID_NULL;
end;
I received the error "Cannot access protecetd symbol TCustonTrayIcon.Data".
What can I fix in the code to properly use the Shell_NotifyIconGetRect function?
Upvotes: 0
Views: 276
Reputation: 596101
Using AllocateHwnd()
for the uID
is absolutely wrong. You need to use the actual ID number that TTrayIcon
registered for its icon.
Your second code is the correct way to go. However, as you have discovered, the Data
property is protected, so you can't access it directly. Fortunately, it is not private, so you can reach it indirectly using an accessor class, eg:
type
TTrayIconAccess = class(TTrayIcon)
end;
FillChar(TrayIconIdentifier, SizeOf(TrayIconIdentifier), #0);
with TrayIconIdentifier do
begin
cbSize := SizeOf(TrayIconIdentifier);
if (TTrayIconAccess(TrayIconForTest).Data.uFlags and NIF_GUID) = 0 then
begin
hWnd := TTrayIconAccess(TrayIconForTest).Data.Wnd;
uID := TTrayIconAccess(TrayIconForTest).Data.uID;
end else
GuidItem := TTrayIconAccess(TrayIconForTest).Data.guidItem;
end;
Upvotes: 1