Delphi, cz. 18
No i doczekaliście się ostatniej części kursu. Nie martwicie się :)) Zajrzyjcie na stronę: www.programowanie.of.pl i poczytajcie trochę artykułów na temat Delphi oraz FAQ. W ostatniej części kursu postaram się rozjaśnić temat podajnika...
Podajnik
Podajnik to ten mały kwadracik na pasku stanu na którym znajdują się m.in. ikony z zegarem Windows. W dalszej części tego rozdziału będę nazywał ten pasek Tray'em. Tak więc Delphi także umożliwia dodanie do Tray'a swoją ikonę i właśnie ten temat postanowiłem poruszyć w tym rozdziale.
Do dodawania swojej ikony do Tray'a służy tylko jedno polecenie "Shell_NotifyIcon". Funkcja ta zadeklarowana jest w module "ShellAPI" tak więc żeby z niej korzystać musisz dodać słowo "ShellAPI" do listy uses.
Funkcja "Shell_NotifyIcon" zawiera dwa parametry. Pierwszym z nich jest akcja, czyli co chcesz zrobić. Możliwe są takie parametry:
NIM_ADD Dodaje nową ikonę do podajnika
NIM_MODIFY Zmiana aktualnej ikony znajdującej się w Tray'u;
NIM_DELETE Usunięcie ikony z podajnika;
Drugim parametrem jest rekord "TNotifyData". Określa on zachowanie naszego programu. Przykładowe wypełnienie tego rekordu mogłoby wyglądać tak:
var
Tray : TNotifyIcon;
begin
Tray.cbSize := SizeOf(Tray);
Tray.Wnd := Handle;
Tray.hIcon := LoadIcon(0, IDI_WINLOGO); // zaladuj ikone
Tray.szTip := 'Program...'; // dymek podpowiedzi
Tray.uFlags := NIF_ICON + NIF_MESSAGE + NIF_TIP; // flagi
Pierwszym jego parametrem jest rozmiar całej struktury. Należy go określać tak jak pokazane to zostało na powyższym przykładzie. Kolejny parametr to uchwyt okna, następny to ikona, która będzie reprezentować naszą aplikacje. Polecenie "LoadIcon" przypominam ładuje ikonę z zasobów. Ja w tym przypadku skorzystałem z ikon systemowych udostępnionych przez Windows. Możliwe są do wykorzystania takie oto ikony:
IDI_APPLICATION, IDI_ASTERISK, IDI_EXCLAMATION, IDI_HAND, IDI_QUESTION, IDI_WINLOGO.
Kolejny parametr struktury "TNotifyIcon" to tzw. dymek, czyli tekst programu, który pojawi się gdy najedzie kursorem na ikonę programu. Następny parametr to flaga. Ja w tym przypadku wykorzystałem wszystkie flagi oznaczająca wykorzystanie odpowiednio: ikony, komunikatów Windows oraz dymków podpowiedzi.
Rekord ten dodatkowo posiada jeszcze jedną pozycję, ale na razie nie będę o tym mówił.
1. W sekcji "private" dodaj zmienna:
Tray : TNotifyIcon;
2. Wygeneruj procedurę "OnCreate" formy i wpisz do niej taki tekst:
Tray.cbSize := SizeOf(Tray);
Tray.Wnd := Handle;
Tray.hIcon := LoadIcon(0, IDI_WINLOGO); // zaladuj ikone
Tray.szTip := 'Program...'; // dymek podpowiedzi
Tray.uFlags := NIF_ICON + NIF_MESSAGE + NIF_TIP; // flagi
Shell_NotifyIcon(NIM_ADD, @Tray); // dodaj do Tray'a
To wszystko. Teraz w chwili odpalenia programu jego ikona będzie widniała w Tray'u. Zwróć uwagę na funkcje "Shell_NotifyIcon". Pierwszy parametr to akcja, która zostaje podjęta, czyli dodanie ikony do podajnika. Kolejny parametr to wskazanie na rekord. Wskazanie te musi następować za pomocą operatora "@".
Dobra, ale na razie nic to nie robi. Jest po prostu ikonka, ale co poza tym? Z tym trzeba się będzie trochę pomęczyć :) Należy bowiem stworzyć nowy komunikat i go obsłużyć.
W sekcji "Interface" ( poniżej słowa uses ) dodaj taki tekst:
{ Komunikat obslugujacy operacje na Tray'u }
const
WM_ICONTOTRAY = WM_USER + 1;
Ok, mamy już własny komunikat. Teraz należy go obsłuzyc. W sekcji "private" dodaj taką stopkę:
procedure TrayProc(var Msg: TMessage); message WM_ICONTOTRAY;
To będzie procedura obsługująca nasz komunikat. W sekcji "Implementation" uzupełnij deklaracje tego komunikatu:
procedure TMainFrm.TrayProc(var Msg: TMessage);
var
P : TPoint;
begin
if Msg.LParam = WM_RBUTTONDOWN then // Jezeli nacisnieto prawy przycisk myszy...
begin
GetCursorPos(P); //.. pobierz wspolrzedne kursora
TrayMenu.Popup(P.X, P.Y); // wyswietl menu
end;
if Msg.LParam = WM_LBUTTONDOWN then // Jezeli uzytkownik nacisnol podwojnie...
ShowWindow(Handle, SW_SHOW); //... pokaz okno
end;
Ten komunikat musi obsługiwać naciśnięcie prawym i lewym przyciskiem w obrębie naszej ikony. O komunikatach była mowa w poprzednich rozdziałach więc nie będę się tutaj rozpisywał na ten temat. Na formie umieść komponent "PopupMenu" i nazwij go "TrayMenu". Możesz do niego stworzyć jakieś pozycje. W tej procedurze w przypadku naciśnięcia prawym przyciskiem pobierane są współrzędne kursora i w tym miejscu wyświetlane jest menu. Jeżeli naciśnięto lewym przyciskiem to po prostu powoduje to pokazanie okna. Tak, polecenie "ShowWindow" także może posłużyć do pokazania okna.
Właściwie to wszystkie klocki są już złożone.
Pamiętasz jak mówiłem o rekordzie "TNotifyIcon"? Mówiłem, że jedna pozycja nie została wypełniona. Ta pozycja to komunikat, który obsługiwać będzie zdarzenia na "Tray'u". To dodatkowe pole powinno wyglądać tak:
Tray.uCallbackMessage := WM_ICONTOTRAY; // komunikat
Dobra. Chyba można już przystąpić do składania programu w jedną całość. A więc forma normalnie się wyświetli. Teraz po próbie zamknięcia formularza zamiast się zamknąć program doda ikonę do Tray'a i się schowa. Ja dodałem do "TrayMenu" dwie pozycje: "O autorze" i taką, która ewidentnie zamyka program.
Tak więc wygeneruj procedurę "OnClose" formy i wpisz taki tekst:
procedure TMainFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Tray.cbSize := SizeOf(Tray);
Tray.Wnd := Handle;
Tray.hIcon := LoadIcon(0, IDI_WINLOGO); // zaladuj ikone
Tray.szTip := 'Program...'; // dymek podpowiedzi
Tray.uFlags := NIF_ICON + NIF_MESSAGE + NIF_TIP; // flagi
Tray.uCallbackMessage := WM_ICONTOTRAY; // komunikat
Shell_NotifyIcon(NIM_ADD, @Tray); // dodaj do Tray'a
Action := caNone; // nie rob nic..
{
Action moze byc takze:
caFree - zwolnij
caNone - nie rob nic
caHide - ukryj
}
ShowWindow(Handle, SW_HIDE); // ukryj forme
end;
Po próbie zamknięcia formularza program ukryje się w Tray'u. Ja dodatkowo w programie zawarłem procedurę, która wyświetla na pasku tytułowym formy tekst ( przesuwa ten tekst ). Nie będę jej omawiał gdyż nie ma ona nic wspólnego z podajnikiem.
Tak wygląda cały kod programu:
(**************************************************************)
(* *)
(* Tray Demo Program for Borland Delphi *)
(* Copyright (c) 2001 by Adam Boduch *)
(* E - mail: boduch@poland.com *)
(* *)
(**************************************************************)
unit MainFrmU;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ShellAPI, StdCtrls, Menus;
{ Komunikat obslugujacy operacje na Tray'u }
const
WM_ICONTOTRAY = WM_USER + 1;
type
TMainFrm = class(TForm)
TrayMenu: TPopupMenu;
MenuExist: TMenuItem;
MenuAbout: TMenuItem;
N1: TMenuItem;
procedure MenuAboutClick(Sender: TObject);
procedure MenuExistClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
Tray: TNotifyIconData;
Done : Boolean; // animacja jest w ruchu?
procedure MoveText(Lines: TStringList); // procedura uruchamiajaca animacje
{ Obsluga komunikatu }
procedure TrayProc(var Msg: TMessage); message WM_ICONTOTRAY;
public
end;
var
MainFrm: TMainFrm;
implementation
{$R *.DFM}
procedure TMainFrm.TrayProc(var Msg: TMessage);
var
P : TPoint;
S : TStringList;
begin
if Msg.LParam = WM_RBUTTONDOWN then // Jezeli nacisnieto prawy przycisk myszy...
begin
GetCursorPos(P); //.. pobierz wspolrzedne kursora
TrayMenu.Popup(P.X, P.Y); // wyswietl menu
end;
if Msg.LParam = WM_LBUTTONDOWN then
begin// Jezeli uzytkownik nacisnol lewy przycisk...
ShowWindow(Handle, SW_SHOW); // pokaz forme
S := TStringList.Create; // utworz zmienna
S.Add('Tray Demo Program'); // dodaj tekst
S.Add('HTTP://WWW.PROGRAMOWANIE.OF.PL');
MoveText(S); // wyywolaj procedure wyswietlajaca animacje
S.Free;
end;
end;
procedure TMainFrm.MenuAboutClick(Sender: TObject);
begin
{ Wyswietlenie okna: "O programie..." }
Application.MessageBox(
' Tray Menu Demo ' + #13#13+
'Copyright (c) 2001 by Adam Boduch'+#13+
'HTTP://WWW.PROGRAMOWANIE.OF.PL'+#13+
'E-mail: boduch@poland.com', 'Info', MB_OK + MB_ICONINFORMATION);
end;
procedure TMainFrm.MoveText(Lines: TStringList);
var
I : Integer;
Count : Byte; // okresla linie tekstu
S : String;
begin
{
Ta procedura nie ma nic wspolnego z Tray'em. Po prostu
przesuwa ona tekst na pasku tytulowym formy.
}
Count := 0; // wyswietl pierwsza linie tekstu
S := Lines.Strings[Count];
while not (Done) do
begin
For I := 0 to 100 do
begin
Application.ProcessMessages;
Sleep(100); // odstep
Insert(' ', S, 1); // dodaj spacje na poczatku zdania
Caption := S;// wyswietl na pasku stanu
if (Done) then
Break;
if I = 100 then // Jezeli tekst dojdzie to punktu 100...
begin
while Pos(' ', S) > 0 do
Delete(S, Pos(' ', S), 1); //... usun wszystkie spacje
Count := Succ(Count); // zwieksz licznik
{
Zmienna "Count" przechowuje informacje o wyswietlanej linii.
Po kazdorazowym wykonaniu tej petli licznik jest zwiekszany
o 1 co owocuje wyswietleniem kolejnej linii.
}
if Count = Lines.Count then Count := 0; // Jezeli nie masz wiecej linii to wyzeruj licznik
S := Lines.Strings[Count]; // wyswiet nowa linie
end;
end;
end;
Lines.Free; // zwolnij zmienna
end;
procedure TMainFrm.MenuExistClick(Sender: TObject);
begin
{
Procedura, ktora konczy dzialanie programu
}
Done := True; // zatrzymaj animacje
Shell_NotifyIcon(NIM_DELETE, @Tray); // usun ikone z Tray'a
Application.Terminate; // zakoncz program
end;
procedure TMainFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Tray.cbSize := SizeOf(Tray);
Tray.Wnd := Handle;
Tray.hIcon := LoadIcon(0, IDI_WINLOGO); // zaladuj ikone
Tray.szTip := 'Program...'; // dymek podpowiedzi
Tray.uFlags := NIF_ICON + NIF_MESSAGE + NIF_TIP; // flagi
Tray.uCallbackMessage := WM_ICONTOTRAY; // komunikat
Shell_NotifyIcon(NIM_ADD, @Tray); // dodaj do Tray'a
Action := caNone; // nie rob nic..
{
Action moze byc takze:
caFree - zwolnij
caNone - nie rob nic
caHide - ukryj
}
ShowWindow(Handle, SW_HIDE);
end;
end.
Tak więc kończę na tym kurs "Delphi 5 dla początkujących". Jeżeli macie jakieś pytania możecie pisać na adres: boduch@poland.com. Tylko błagam Was! Najpierw wejdźcie na stronę: www.programowanie.of.pl, poczytajcie FAQ, artykuły o Delphi, a może wyjaśni się wiele Waszych problemów.
Pozostało mi jeszcze życzyć Wam najlepszych programów. I pamiętajcie! Cały czas się uczcie więc ściągajcie sobie źródła i przykładowe programy.
KONIEC.
Adam Boduch dnia: 4 marzec 2001 16:23:49 |