yonni
yonni

Reputation: 352

Using the Shell_NotifyIconGetRect function for TTrayIcon

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

Answers (1)

Remy Lebeau
Remy Lebeau

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

Related Questions