0

I created a small application that allows minimizing to the system tray by clicking on a pop-up menu item associated with the form.

The application adds an icon by calling the Shell_NotifyIcon function and hides itself. To restore, simply click on the icon in the tray, the form is displayed and the icon disappears.

This all works as expected when I run the application from the project folder, but when it is run from another location (any location), the icon creation fails, with the error code I get using GetLastError being 0x80004005.

Here is the execution code:

procedure TMyForm.BMHideClick(Sender: TObject);
begin
  Hide;
  PowerNotifyIcon.uFlags := NIF_MESSAGE or NIF_ICON or NIF_GUID or NIF_TIP; {PowerNotifyIcon is a TNotifyIconData structure}
  StrPLCopy(PowerNotifyIcon.szTip, ICON_TIP, Length(ICON_TIP)); {ICON_TIP is a predefined string constant}
  if not Shell_NotifyIcon(NIM_ADD, @PowerNotifyIcon) then
  begin
    MessageBox(Handle, PChar(Format('Failed to create system tray icon. error code: 0x%x', [GetLastError])),
      PChar('Error'), MB_OK or MB_ICONERROR);
    Show;
    Exit;
  end;
  Shell_NotifyIcon(NIM_SETVERSION, @PowerNotifyIcon);
end;

To restore the form, I handle the WM_SYSTEM_TRAY_MESSAGE messages received from the icon:


procedure TMyForm.TrayIconProc(var Msg: TMessage);
begin
  case LOWORD(Msg.LParam) of
    {...}
    NIN_SELECT, NIN_KEYSELECT, WM_CONTEXTMENU, WM_LBUTTONUP, WM_RBUTTONUP: begin
      Show;
      Shell_NotifyIcon(NIM_DELETE, @PowerNotifyIcon);
    end;
  end;
end;
wohlstad
  • 12,661
  • 10
  • 26
  • 39
yonni
  • 248
  • 2
  • 11
  • 2
    See [Proper Way of Handling GUID used by Windows NotificationIcons](https://stackoverflow.com/q/73334917/1889329). In short: The system works as designed. The fix: Remove the GUID registration. – IInspectable Aug 15 '22 at 10:38
  • Or sign the app. – Jonathan Potter Aug 15 '22 at 13:01
  • `Shell_NotifyIcon()` is not documented to report error codes via `GetLastError()`, so you can't rely on the error code being meaningful if `Shell_NotifyIcon()` returns False. – Remy Lebeau Aug 15 '22 at 18:22
  • @IInspectable Of course you were right. This weird GUID feature is to blame... – yonni Aug 15 '22 at 20:31
  • @Remy How can I tell what is the cause of the error if `Shell_NotifyIcon` fails? – yonni Aug 15 '22 at 20:45
  • 1
    You can't. This API returns a boolean value (success/failure) without any additional information. It's likely as old as the GDI, which also doesn't report failure context by way of `GetLastError` (for msot of its API surface). It's not an ideal situation, but the solution (a time machine) doesn't appear to be readily available either. – IInspectable Aug 15 '22 at 21:14

0 Answers0