Programowanie w języku Delphi » Gotowce

Jak dodać ikonę do traya

  • 2007-06-05 11:36
  • 17 komentarzy
  • 1901 odsłon
  • Oceń ten tekst jako pierwszy
Są dwie rzeczy, które trzeba wziąć pod uwagę tworząc aplikację do tray'a. Pierwsza to ukrycie aplikacji przed Windows. Mimo, że aplikacje takie wyglądają i zachowują się jak zwykłe aplikacje Windows, nie można się na nie przełączyć przy użyciu Alt-Tab ani nie mają swojego przycisku na pasku zadań. Tym zajmiemy się najpierw.
Każde okno posiadające styl WS_EX_TOOLWINDOW ani nie ma przycisku na pasku zadań ani nie można się na nie przełączyć. Z początku może wydawać się właściwym ustawienie tego stylu przy użyciu CreateParams. Niestety nie zadziała to dla formy. Tu mała dygresja. Główna forma aplikacji nie jest oknem (w terminologii Windows) aplikacji. Obiekt aplikacji ma swoje własne okno - nie można go zobaczyć
              ale ono tam jest. To jest właśnie to okno, do którego należy przypisać styl WS_EX_TOOLWINDOW. Gdzie więc należy wstawić kod? Oczywiście w źródle projektu. Po wybraniu View|Project Source należy skopiować poniższy kod:
             
program Project1;  
 uses 
Forms, Unit1 in 'Unit1.pas' {Form1}, 
Windows;//To jest wymagane aby znana była stała WS_EX_TOOLWINDOW i pozostałe         
 
{$R *.RES}
 
 var
 ExtendedStyle : Integer;  //Deklaracja zmiennej do przyjęcia informacji o stylu okna
 
 begin
Application.Initialize;
 //Pobranie informacji o oknie aplikacji przy użyciu GetWindowLong
 ExtendedStyle:=GetWindowLong(Application.Handle, GWL_EXSTYLE);
 
//Teraz ustawiamy styl rozszerzony przy użyciu operacji na bitach
//Przekształca to okno z okna-aplikacji do okna-narzędzia
SetWindowLong(Application.Handle,GWL_EXSTYLE,ExtendedStyle or WS_EX_TOOLWINDOW and 
not WS_EX_APPWINDOW);
            Application.CreateForm(TForm1, Form1); 
            Application.Run;
              end.

A teraz aby utworzyć właściwy efekt aplikacji w trayu będziemy potrzebowali przede wszystkim głównej formy aplikacji. Połóż na formie komponent TPopupMenu. Będzie to główny interfejs do naszej aplikacji. Popatrz na poniższy kod:
{ Poniższe umieszcza aplikację w trayu. Jest to główna forma aplikacji. Posiada ona menu popup używane do wyświetlenia formy i zamknięcia aplikacji. Używając modułu ShellApi w prosty sposób pokażemy ikonę aplikacji w trayu i spowodujemy aby reagowała na kliknięcia myszą } 
 
              unit Unit1;
             interface
 
             uses
               Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
               ShellAPI, ExtCtrls, Menus;
 
              type
               TForm1 = class(TForm)
               PopupMenu1: TPopupMenu;
               ShowMainForm1: TMenuItem;
               N1: TMenuItem;
               ExitApplication1: TMenuItem;
              procedure FormCreate(Sender: TObject);
             procedure ShowMainForm1Click(Sender: TObject);
             procedure FormClose(Sender: TObject; var Action: TCloseAction);
              procedure ExitApplication1Click(Sender: TObject);
              private
              procedure WndProc(var Msg : TMessage); override;
              public
              IconNotifyData : TNotifyIconData;
              end;
 
            var
              Form1: TForm1;
 
              implementation
 
              {$R *.DFM}
 
              procedure TForm1.FormCreate(Sender: TObject);
              begin
               // Zostawiamy tylko przycisk zamykający okno
               BorderIcons := [biSystemMenu];
 
              // Teraz wypełniamy rekord IconNotifyData tak aby przyjmował
              // komunikaty wysyłane do aplikacji i pokazywał dymki podpowiedzi.
              with IconNotifyData do begin
              hIcon:=Application.Icon.Handle;
              uCallbackMessage:=WM_USER+1;
              cbSize:=SizeOf(IconNotifyData);
             Wnd:=Handle;
             uID:=100;
             uFlags:=NIF_MESSAGE+NIF_ICON+NIF_TIP;
             end;
              // Kopiujemy tytuł aplikacji jako ;dymek;
               StrPCopy(IconNotifyData.szTip, Application.Title);
 
              // Dodajemy ikonę do traya
               Shell_NotifyIcon(NIM_ADD,@IconNotifyData);
              end;
 
              procedure TForm1.WndProc(var Msg : TMessage);
              var
             p : TPoint;
              begin
              if (Msg.Msg=WM_USER+1) and (Msg.lParam=WM_RBUTTONDOWN) then
               begin
               GetCursorPos(p);
              PopupMenu1.Popup(p.x, p.y);
              end; inherited;
             end;
 
              // To jedna z procedur obsługi elementów menu
              procedure TForm1.ShowMainForm1Click(Sender: TObject);
              begin
               Form1.Show;
              end;
 
              procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
              begn
               Action := caNone;
               Form1.Hide;
              end;
 
              procedure TForm1.ExitApplication1Click(Sender: TObject);
              begin
               Shell_NotifyIcon(NIM_DELETE, @IconNotifyData);
               Application.ProcessMessages;
               Application.Terminate;
              end;
              end.

Jak widać nie ma wiele do zrobienia. Ale ważne jest aby rozumieć co zrobiliśmy w metodzie Create i jakie znaczenie ma rekord IconNotifyData. Jest to rekord zdefiniowany w module ShellAPI, który przechowuje informację o ikonie w trayu. Zauważ flagi, których użyliśmy: NIF_MESSAGE + NIF_ICON + NIF_TIP. Oznaczają one kolejno: obsługę komunikatów dla aplikacji, pokazywanie ikony aplikacji i pokazywanie dymku z podpowiedzią.
Następna sprawa to nadpisanie procedury WndProc (skrót od WindowProcedure). Dostaje ona wszystkie komunikaty przesyłane do okna i zachowuje się jak centralna rozdzielnia komunikatów. Można przejąć obsługę komunikatu pisząc własną jego obsługę i wywołując odziedziczoną procedurę. Przy obsłudze komunikatu sprawdzamy czy jest to nasz własny (wm_User+1) zdefiniowany w zmiennej IconNotifyData oraz czy nastąpiło
              kliknięcie prawym przyciskiem myszy. Pozostałe komunikaty przesyłamy bez zmian.[...]

17 komentarzy

luszko 2009-08-28 13:57

Mi wyskakuje seria błędów! Połowę kodu zaznacza na czerwono!

elvispm 2009-07-16 19:13

nie wiem co się dzieje ale  nie wyświetla mi popupmenu, reszta śmiga dobrze.

maxi 2008-06-13 19:54

Delphi 2006 ma wbudowany komponent do tego (coś jak w Builderze), jak macie możliwość żeby go użyć to polecam, jest dużo wygodniejszy :)

sjmlo 2007-10-11 12:59

Wszystko fajnie, tylko nie usuwa aplikacji z ALT+TAB, jak zrobic zeby usuwalo??

nav 2007-06-07 16:40

Shell_NotifyIcon(NIM_DELETE,@icon);

tomasz.mistal 2007-05-07 13:17

Witam wszystkich.
Powiedzcie mi jak mogę usunąć ikonkę z tray'a.
 Dzięki..

dzikimisiu 2005-03-26 12:52

czesc jest taki kod
procedure TForm1.WndProc(var Msg : TMessage);

              var

                p : TPoint;

              begin

                if (Msg.Msg=WM_USER+1)and(Msg.lParam=WM_RBUTTONDOWN) then

                begin

                 GetCursorPos(p);

                 PopupMenu1.Popup(p.x, p.y);

                end; inherited;

              end;

             

              // To jedna z procedur obsługi elementów menu

              procedure TForm1.ShowMainForm1Click(Sender: TObject);

              begin

                Form1.Show;

              end;
i mam pytanie gdzie go doda??

dawidmo 2004-06-30 14:19

Nie chce pisać na temat tego ArtuMam zasadnicze pytanie jak dodać pogram do treja który nie zawiera Formy bo jak wiadomo program skompilowany bez bibliotek alboz samym WINDOWS zajmuje jakieś 16 Kb w Delphi 7

Tytus 2004-06-21 16:43

Żeby menu znikało po kliknięciu np. na pulpicie trzeba przed pokazaniem menu (w funkcji WndProc) wywołać funkcję SetForegroundWindow(Handle):
         if (Msg.Msg=WM_USER+1)and(Msg.lParam=WM_RBUTTONDOWN) then
         begin
          SetForegroundWindow(Handle)
          GetCursorPos(p);
......

blackrage 2004-06-01 02:08

Ten tekst widziałem już w wielu faqach (identyczny), ale niestety to rozwiązanie jest złe!
Popup nie znika jesli klikniemy na pulpit, a powinien.

Kane-power 2004-04-23 15:00

no dobra, niby dziala ale teraz pisze ze file not found *.dcu .........

Kane-power 2004-04-23 14:52

gdzie ja mam wstawci pierwsza czesc kodu??>
nie mam czegos takiego jak view|source code

mam wstawic do Unit1.pas??

wstawilem tylko 2 czesc, dziala ale nie wyswietla mojego popupmenu, jak zrobic zeby wyswietlało?

Kane-power 2004-04-23 14:43

gdzie ja mam wstawci pierwsza czesc kodu??>
nie mam czegos takiego jak view|source code

mam wstawic do Unit1.pas??

wstawilem tylko 2 czesc, dziala ale nie wyswietla mojego popupmenu, jak zrobic zeby wyswietlało?

Sebek 2002-12-18 08:48

Ah tu był mój komentarz ale już go niema bo źle zrozumiałem intecje pop. autrów komentarzy :) czyli ten art był przeniesiony?

Ktos 2002-12-06 15:01

nie, to się raczej nadaje do FAQ :) A chyba nawet tam jest coś podobnego...

Adam Boduch 2002-12-05 12:51

Ludzie, to sie nadaje do dzialu Gotowce, a nie tutaj!!!