Delphi: Minimize application to systray
Asked Answered
D

4

2

I want to minimize a Delphi application to the systray instead of the task bar.

The necessary steps seem to be the following:

  1. Create icon which should then be displayed in the systray.
  2. When the user clicks the [-] to minimize the application, do the following:
    1. Hide the form.
    2. Add the icon (step #1) to the systray.
    3. Hide/delete the application's entry in the task bar.
  3. When the user double-clicks the application's icon in the systray, do the following:
    1. Show the form.
    2. Un-minimize the application again and bring it to the front.
    3. If "WindowState" is "WS_Minimized" set to "WS_Normal".
    4. Hide/delete the application's icon in the systray.
  4. When the user terminates the application, do the following:
    1. Hide/delete the application's icon in the systray.

That's it. Right?

How could one implement this in Delphi?

I've found the following code but I don't know why it works. It doesn't follow my steps described above ...

unit uMinimizeToTray;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellApi;

const WM_NOTIFYICON = WM_USER+333; 

type
  TMinimizeToTray = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure CMClickIcon(var msg: TMessage); message WM_NOTIFYICON;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  MinimizeToTray: TMinimizeToTray;

implementation

{$R *.dfm}

procedure TMinimizeToTray.CMClickIcon(var msg: TMessage);
begin
  if msg.lparam = WM_LBUTTONDBLCLK then Show;
end;

procedure TMinimizeToTray.FormCreate(Sender: TObject);
VAR tnid: TNotifyIconData;
    HMainIcon: HICON;
begin
  HMainIcon := LoadIcon(MainInstance, 'MAINICON');
  Shell_NotifyIcon(NIM_DELETE, @tnid);
  tnid.cbSize := sizeof(TNotifyIconData);
  tnid.Wnd := handle;
  tnid.uID := 123;
  tnid.uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
  tnid.uCallbackMessage := WM_NOTIFYICON;
  tnid.hIcon := HMainIcon;
  tnid.szTip := 'Tooltip';
  Shell_NotifyIcon(NIM_ADD, @tnid);
end;

procedure TMinimizeToTray.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caNone;
  Hide;
end;

end.
Donnell answered 22/5, 2010 at 18:37 Comment(5)
It used to be that the TApplication was the one that created the taskbar entry, and the TForms were free to act independently. Has this changed as of late?Declinatory
What version of Delphi are you using? In newer versions, there is a TTrayIcon in the VCL, that you can use to create the tray icon, at least.Encrust
The code is different with your steps in that; - the systray icon is always visible, - it does not interfere with 'minimizing' (there's no step 2), when the icon is double clicked it shows the form which was hidden by clicking the close box [X], - and also it does not take terminating into account (there's no step 4).Ticktack
The TTrayIcon with implementing the DoubleClick and ApplicationMinimize events is the easiest using VCL components.Nolpros
@Andreas Rejbrand: Unfortunately, I use Delphi 7. It doesn't seem to be implemented there.Donnell
C
4

I would recommend using CoolTrayIcon. The author has already worked out all the issues involved with tray icons. Its free with source and examples and very debugged.

http://subsimple.com/delphi.asp

Crake answered 22/5, 2010 at 19:27 Comment(1)
This component works fine. It does everything one wants to have for a TrayIcon. Thank you!Donnell
D
5

If it still works, it's probably easiest to use JVCL's TJvTrayIcon to handle it automatically.

Declinatory answered 22/5, 2010 at 18:45 Comment(2)
Probably, I'm just to stupid, but I didn't found a download link for this. Thanks, though! ;) If you look at the +3 votes, your answer seems to be good ...Donnell
It's the "Downloads" link on the left at the first link.Declinatory
C
4

I would recommend using CoolTrayIcon. The author has already worked out all the issues involved with tray icons. Its free with source and examples and very debugged.

http://subsimple.com/delphi.asp

Crake answered 22/5, 2010 at 19:27 Comment(1)
This component works fine. It does everything one wants to have for a TrayIcon. Thank you!Donnell
M
1

Instead of Application.BringToFront; use SetforegroundWindow(Application.Handle);

Mornings answered 27/10, 2018 at 14:31 Comment(0)
D
-1

In the following text I'll be referring to the step numbers mentioned in the question:

The following solution is without any additional components. It's very easy to implement.

Step #1:

Just use the application's main icon (see following code).

Step #2:

procedure TForm1.ApplicationEvents1Minimize(Sender: TObject);
begin
  Shell_NotifyIcon(NIM_ADD, @TrayIconData);
  Form1.Hide;
end;

Step #3:

procedure TForm1.TrayMessage(var Msg: TMessage);
begin
  if Msg.lParam = WM_LBUTTONDOWN then begin
    Form1.Show;
    Form1.WindowState := wsNormal;
    Application.BringToFront;
    Shell_NotifyIcon(NIM_DELETE, @TrayIconData);
  end;
end;

Step #4:

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Shell_NotifyIcon(NIM_DELETE, @TrayIconData);
end;

Necessary code in interface part:

uses
  [...], ShellApi;

const
  WM_ICONTRAY = WM_USER + 1;

type
  TForm1 = class(TForm)
    [...]
    procedure TrayMessage(var Msg: TMessage); message WM_ICONTRAY;
  end;

The only problem: The application can be minimized to the systray only once. The next time you want to minimize it, nothing will happen. Why?

Source: delphi.about.com

Donnell answered 23/5, 2010 at 22:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.