Entwickler-Ecke

Windows API - ...Icons in die TNA hinzufügen, ändern und löschen?


Tino - Fr 07.03.03 14:09
Titel: ...Icons in die TNA hinzufügen, ändern und löschen?
Um mit Icons in der TNA (TNA = Taskbar Notification Area)[meta]Icon neben Uhr, unten rechts[/meta] zu arbeiten benötigen wir die Shell_NotifyIcon Funktion welche in der Unit ShellAPI.pas importiert wird. Also nicht vergessen diese Unit in die Uses-Klausel aufzunehmen.

Die Funktion Shell_NotifyIcon erwartet zwei Paramter:
Da es sich bei Shell_NotifyIcon um eine Funktion handelt bekommen wir natürlich auch ein Ergebnis zurück. Die Funktion liefert True wenn alles geklappt hat und False bei einem Fehler zurück.

Aufbau von TNOTIFYICONDATA:
Hier nur ein Beispiel wie man ein Icon in die TNA hinzufügt. Erstmal müssen wir die Unit ShellAPI einbinden:

Delphi-Quelltext
1:
2:
uses
  ShellAPI;

Dann brauchen wir eine Variable vom Typ TNOTIFYICONDATA. Diese definieren wir in der Private-Sektion der Form:

Delphi-Quelltext
1:
2:
private
  fIconData: TNOTIFYICONDATA;

Im OnCreate-Event der Form wird das Icon in die TNA hinzugefügt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TForm1.FormCreate(Sender: TObject);
begin
  // NotifyIconData-Struktur mit Werten füllen
  with fIconData do
    begin
      cbSize := SizeOf (TNOTIFYICONDATA);
      Wnd := Handle;
      uID := 1;
      uFlags := NIF_ICON + NIF_TIP;
      hIcon := LoadIcon (0, IDI_INFORMATION);
      szTip := 'Tooltip';
    end;

  // Icon in die TNA hinzufügen
  If not Shell_NotifyIcon (NIM_ADD, @fIconData) then
    { Fehler! };
end;

Um das Icon zu entfernen muss statt NIM_ADD die Konstante NIM_DELETE benutzt werden (in unserem Beispiel wird das Icon im OnDestroy-Event der Form entfernt):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.FormDestroy(Sender: TObject);
begin
  // Icon aus der TNA entfernen
  if not Shell_NotifyIcon (NIM_DELETE, @fIconData) then
    { Fehler! };
end;

Möchten wir zum Beispiel das Icon und/oder den Tooltip ändern müssen wir wie folgt vorgehen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.Button1Click(Sender: TObject);
begin
  // Erst die Änderungen in der NotifyIconData-Struktur vornehmen
  with fIconData do
    begin
      hIcon := LoadIcon (0, IDI_WARNING);
      szTip := 'Neuer Tooltip';
    end;

  // Dann die Änderungen in der TNA durchführen lassen
  if not Shell_NotifyIcon (NIM_MODIFY, @fIconData) then
    { Fehler! };
end;

So, jetzt wissen wir bereits wie man Icons, hinzufügt, ändert und löscht. Aber es fehlt natürlich noch etwas. Wir müssen auf verschiedene Aktionen, die mit dem Icon vom User durchgeführt werden können, reagieren können. Windows verschickt bei jeder Aktion (klicken, doppelklick, etc) eine Message die wir dann auswerten müssen. Als erstes definieren wir eine neue Message-Konstante:

Delphi-Quelltext
1:
2:
const
  cWM_MYTRAYICONCALLBACK = WM_USER + 1000;

Dann müssen wir eine Procedure definieren die die Messages empfängt. Dazu definieren wir in der Private-Sektion der Form die Procedure:

Delphi-Quelltext
1:
2:
Private
  procedure TaskTrayWndProc (var Msg: TMessage); message cWM_MYTRAYICONCALLBACK;

Die Implementation dieser Procedure könnte wie folgt aussehen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm1.TaskTrayWndProc (var Msg: TMessage);
begin
  case Msg.LParam of
    WM_LBUTTONDOWN:
      MessageDlg ('Linke Maustaste gedrückt!', mtInformation, [mbOK], 0);
    WM_RBUTTONDOWN:
      MessageDlg ('Rechte Maustaste gedrückt!', mtInformation, [mbOK], 0);
  end;
end;

Damit Windows jetzt auch weiß welche Message es verschicken muss müssen wir dies beim erstellen des Icons angeben. Deshalb ist folgende Änderung in dem OnCreate-Event notwendig:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
  with IconData do
    begin
      cbSize := SizeOf (TNOTIFYICONDATA);
      Wnd := Handle;
      uID := 1;
      uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
      hIcon := LoadIcon (0, IDI_INFORMATION);
      szTip := 'Tooltip';
      uCallBackMessage := cWM_MYTRAYICONCALLBACK;
    end;


Sollte, aus welchen Gründen auch immer, der Explorer von Windows abstürzten und sich anschl. neu starten so sendet der Explorer die Windows Message TaskbarCreated an alle Top-Level-Fenster damit diese dann, falls vorhanden, ihr Icon wieder in die TAN hinzufügen können. Ein Beispiel von user profile iconMartin1966 findest du hier [http://www.delphi-forum.de/viewtopic.php?p=379878#379878].

Solltest du an einer fertigen Komponente interessiert sein die all die hier genanten Funktionen (und noch viele weitere) schon fertig verpackt unterstützt so kann ich dir die CoolTrayIcon [http://subsimple.com/delphi.asp] Komponente von Troels Jakobsen empfehlen.