r08 cpl t (3)


Kreator apletów panelu sterowania
W systemach z rodziny Windows 3.x aplety dostępne w Panelu sterowania służyły
przede wszystkim do konfigurowania sprzętu. Obecnie
w systemach Windows 95,
98 i 2000
ich zastosowania obejmują także definiowanie ustawień
oprogramowania, w tym wielu aplikacji.
Użycie apletu pozwala skonfigurować aplikację bez konieczności jej uruchamiania
i wybierania odpowiednich poleceń z menu. Postępowanie sprowadza się wówczas do
wywołania odpowiedniego apletu z Panelu sterowania i zmiany odpowiednich
ustawień. Rozwiązanie to pozwala "odchudzić" kod aplikacji poprzez usunięcie z
niego elementów konfiguracyjnych, a ponadto umożliwia centralizację zarządzania
ustawieniami sprzętu i oprogramowania.
Dostępny w C++Builderze 5 kreator apletów znacznie upraszcza tworzenie ich kodu
oraz elementów składowych (ikony, formularze i opisy).
Podstawy działania apletu
Aplet jest niewielkim, wyspecjalizowanym programem narzędziowym umożliwiającym
sterowanie zachowaniem danego urzÄ…dzenia lub programu (i stosowanym tylko w tym
celu). Pozwala on zmieniać ustawienia kontrolowanej aplikacji bez konieczności
jej uruchamiania. W systemie Windows aplety uruchamiane uruchamiane sÄ… z okna
Panelu sterowania (zobacz rysunek 8.4).
Rysunek 8.4. Panel sterowania systemu Windows 2000
Z technicznego punktu widzenia aplet jest zwykłą biblioteką dynamiczną o
rozszerzeniu nazwy .cpl. W chwili uruchomienia, aplikacja zarzÄ…dzajÄ…ca apletami
ładuje plik .cpl do pamięci i pobiera z niego niezbędne informacje, przekazując
doń odpowiednie komunikaty i odbierając dane za pośrednictwem specjalnej
funkcji zwrotnej CPlApplet(). Zarządzaniem apletami zajmuje się na ogół Panel
sterowania (program control.exe), jednak może to robić dowolna inna aplikacja.
W pojedynczym pliku .cpl może mieścić się kilka apletów "logicznych",
reprezentowanych np. przez dwie różne ikony, wykorzystujących dwa okna
dialogowe (formularze) i służących do konfigurowania dwóch różnych aplikacji.
Przykładami mogą tu być aplety System i Dodaj/Usuń sprzęt w systemach Windows
95 i 98. Oba one zawarte sÄ… w pliku Windows/System/Sysdm.cpl, jednak wykonujÄ…
różne zadania i w oknie Panelu sterowania reprezentowane są dwiema różnymi
ikonami. Z tego względu, mimo fizycznego połączenia w jedną całość, można
traktować je jako logicznie odrębne narzędzia.
Komunikacja pomiędzy apletem a zarządzającą nim aplikacją polega na wymianie
komunikatów poprzez funkcję CPlApplet(). Aplet odpowiada na komunikaty wysyłane
przez aplikację, przesyłając do niej dane, które z kolei pozwalają sterować
jego działaniem. Rodzaj danych zwracanych przez aplet określony jest
parametrami komunikatów przekazywanych przez aplikację zarządzającą. Istotna
jest również kolejność przesyłania komunikatów, co narzuca określone reguły
tworzenia kodu apletu.
Tabela 8.3 Kolejność i znaczenie komunikatów przesyłanych do apletu
Komunikat
Znaczenie
CPL_INIT (wartość stałej = 1)
Przesyłany jako pierwszy, bezpośrednio po załadowaniu kodu apletu do pamięci
Komunikat ten służy do inicjalizacji apletu. Parametry lParam1 i lParam2 nie są
używane. W przypadku pomyślnej inicjalizacji, funkcja CPlApplet() powinna
zwrócić wartość TRUE, sygnalizując możliwość kontynuacji pracy. W przeciwnym
razie zwracana jest wartość FALSE, nakazująca zakończenie wymiany danych i
usunięcie kodu apletu z pamięci.
CPL_GETCOUNT (wartość stałej = 2)
Przesyłany po komunikacie CPL_INIT; zwracana wartość powinna być większa od
zera
W odpowiedzi na ten komunikat funkcja CPlApplet() zwraca liczbę apletów
logicznych (okien dialogowych) zawartych w pliku .cpl i reprezentowanych w
postaci ikon w Panelu sterowania. Wartość ta powinna być większa od zera.
Parametry lParam1 i lParam2 nie są używane.
CPL_INQUIRE (wartość stałej = 3)
Przesyłany po komunikacie CPL_GETCOUNT, dokładnie raz dla każdego okna
dialogowego (apletu logicznego) zawartego w pliku .cpl. Okna liczone sÄ… od
zera; numer okna przekazywany jest w parametrze lParam1.
Komunikat ten nakazuje zwrócenie informacji o poszczególnych apletach
logicznych. Parametr lParam1 określa numer apletu, zaś lParam2 zawiera wskaźnik
do struktury typu CPLINFO, zawierajÄ…cej informacje o aplecie (ikona, nazwa,
opis).
CPL_NEWINQUIRE (wartość stałej = 8)
Odpowiednik komunikatu CPL_INQUIRE (aplikacja zarządzająca przesyła oba
komunikaty)
Znaczenie tego komunikatu jest zbliżone do CPL_INQUIRE, jednak parametr lParam2
wskazuje tym razem na strukturę NEWCPLINFO, zawierającą m.in. dane zależne od
stanu systemu. Dla poprawy wydajności w systemach Windows 95, NT i nowszych
zaleca się używanie komunikatu CPL_INQUIRE.
CPL_DBLCLK (wartość stałej = 5)
Sygnalizuje dwukrotne kliknięcie ikony apletu
Komunikat ten wysyłany jest po dwukrotnym kliknięciu ikony apletu (czyli jego
wywołaniu). Parametr lParam1 zawiera numer wywoływanego apletu logicznego, zaś
lParam2
wartość pola lData struktury CPLINFO. Wynikiem przetworzenia
komunikatu powinno być wyświetlenie okna dialogowego (formularza) apletu.
CPL_STOP (wartość stałej = 6)
Przesyłany bezpośrednio przed zakończeniem działania aplikacji zarządzającej,
dokładnie jeden raz dla każdego apletu logicznego (numer apletu przekazywany
jest w parametrze lParam1)
Komunikat ten sygnalizuje zakończenie działania aplikacji zarządzającej i
przesyłany jest dokładnie raz do każdego apletu. W ramach jego obsługi aplet
powinien zwolnić wykorzystywane zasoby i wykonać inne lokalne operacje
"porzÄ…dkujÄ…ce". Parametr lParam1 zawiera numer apletu; lParam2
wartość pola
lData struktury CPLINFO.
CPL_EXIT (wartość stałej = 7)
Wysyłany jednokrotnie po przesłaniu wszystkich komunikatów CPL_STOP.
Bezpośrednio po jego przetworzeniu wywoływana jest funkcja FreeLibrary(),
usuwająca kod pliku .cpl z pamięci.
Komunikat ten przesyłany jest przez aplikację zarządzającą bezpośrednio przed
wywołaniem funkcji FreeLibrary(), usuwającej z pamięci kod apletów zawartych w
pliku .cpl. W ramach jego obsługi należy zwolnić zasoby (pamięć, uchtywy plików
itd.) wspólne dla apletów logicznych, tj. używane globalnie dla całego pliku
.cpl.
Powyższa lista wygląda dość groźnie, ale nie ma się czym przerażać
C++Builder
automatycznie obsługuje wszystkie komunikaty sterujące działaniem apletu. Do
szybkiego utworzenia apletu można wykorzystać dostępny w C++Builderze kreator
(Control Panel Applet Wizard), co zademonstrujemy za chwilÄ™. AlternatywnÄ…
metodę, opartą na wywołaniach funkcji Win32 i nie wykorzystującą kreatora,
opiszemy w rozdziale 24.
Uwaga
W naszym przykładzie nie będziemy zajmować się tworzeniem ikony apletu

zakładamy, że Czytelnik potrafi już tworzyć pliki ICO za pomocą edytora
graficznego. Ikonę niezbędną dla konstruowanego w przykładzie apletu można
utworzyć samodzielnie lub pobrać z gotowego pliku.
A zatem zaczynamy. Uruchom IDE i wybierz polecenie Close All z menu File,
zamykając w ten sposób wszystkie otwarte pliki i projekty. Następnie wybierz
polecenie File|New. W wyświetlonym na ekranie oknie składnicy obiektów (New
Items) kliknij dwukrotnie ikonÄ™ Control Panel Application (zobacz rysunek 8.5).
Zwróć przy okazji uwagę na znajdującą się obok ikonę Control Panel Module

umożliwia ona dodanie apletu do tworzonego pliku .cpl.
Rysunek 8.5. Uruchomienie kreatora apletów panelu sterowania
Po uruchomieniu, kreator utworzy szkielet kodu i najważniejsze dane niezbędne
do działania apletu. Wyświetlane przezeń okno przypomina nieco kreator modułów
danych (Data Module Designer) i zawiera dwie karty
Components (komponenty) i
Data Diagram (schemat danych), co widać na rysunku 8.6. Wynikiem działania
kreatora jest utworzenie klasy TAppletModule1, implementujÄ…cej aplet. Jej kod
można obejrzeć po naciśnięciu klawisza F12.
Rysunek 8.6. Okno eksploratora modułów
Kod apletu bazuje na module C++Buildera o nazwie CtlPanel, którego kod
realizuje większość czynności związanych ze standardową obsługą apletu. Trzy
najważniejsze elementy wchodzące w skład modułu CtlPanel to klasa wyjątku
EAppletException oraz klasy TAppletApplication i TAppletModule.
TAppletApplication to klasa singletonowa (tj. dopuszczajÄ…ca utworzenie tylko
jednego egzemplarza
przyp. tłum.) służąca jako pojemnik dla obiektów
(modułów) typu TAppletModule. W naszym przykładzie używamy tylko jednego
modułu, jednak w razie potrzeby można dołączyć do apletu kolejne obiekty
TAppletModule (co odpowiada zdefiniowaniu kolejnych apletów logicznych w ramach
danego pliku .cpl). W tym celu należy wydać polecenie New z menu File i w
wyświetlonym oknie składnicy obiektów wybrać ikonę Control Panel Module.
Utworzony w ten sposób moduł zostanie dołączony do wybranego pliku .cpl (tj.
"wstawiony" do odpowiedniego obiektu TAppletApplication).
W module CtlPanel zdefiniowano globalnÄ… zmiennÄ… typu TAppletApplication,
reprezentującą aplikację macierzystą dla wszystkich apletów logicznych
tworzonych w ramach danego projektu. W chwili utworzenia projektu, w kodzie
programu tworzony jest wskaźnik Application, reprezentujący aplikację. W
przypadku apletu wskaźnikowi temu przypisywany jest adres obiektu klasy
TAppletApplication, zawierającego z kolei moduł TAppletModule, reprezentujący
pojedynczy aplet logiczny.
Właściwości klasy TAppletModule
C++Builder udostępnia szereg właściwości pozwalających kontrolować różne
aspekty zachowania apletu (ikona, nazwa, opis). Okno inspektora obiektów
prezentujące właściwości klasy TAppletModule pokazano na rysunku 8.7.
Rysunek 8.7. Właściwości obiektu AppletModule1 w oknie inspektora obiektów
A oto znaczenie poszczególnych właściwości.
Właściwość AppletIcon określa ikonę reprezentującą aplet w oknie Panelu
sterowania. Dla kolejnych dołączanych do projektu modułów (apletów) używa się
na ogól oddzielnych ikon, zawartych w plikach zasobów typu ICO. Dwukrotne
kliknięcie pola właściwości powoduje wyświetlenie okna edytora obrazków,
umożliwiającego wybór ikony zapisanej w pliku ICO. Wybrana w ten sposób ikona
będzie wyświetlana w oknie Panelu sterowania.
Właściwość Caption definiuje podpis wyświetlany pod ikoną apletu (tj. jego
nazwÄ™).
Właściwość Help określa tekst opisu apletu, wyświetlany po jego wybraniu w
pasku stanu okna Panelu sterowania (tekst ten zawiera zwykle krótkie
objaśnienie przeznaczenia apletu).
Właściwość ResidIcon zawiera identyfikator zasobu reprezentującego ikonę
apletu. Jej użycie wyklucza możliwość użycia właściwości AppletIcon (i vice
versa; ograniczenie to odnosi się również do pozostałych dwóch właściwości).
Właściwość ResidInfo to identyfikator zasobu reprezentującego łańcuch opisu
apletu. Jej użycie wyklucza możliwość użycia właściwości Help.
Właściwość ResidName jest identyfikatorem zasobu reprezentującego łańcuch nazwy
apletu. Jej użycie wyklucza możliwość użycia właściwości Caption.
W przypadku tworzenia plików zawierających pojedyncze aplety logiczne używa się
na ogół właściwości AppletIcon, Caption i Help, ignorując tym samym właściwości
ResidIcon, ResidInfo i ResidName.
Zdarzenia klasy TAppletModule
Zdarzenia zdefiniowane dla klasy TAppletModule pokazano na rysunku 8.8. System
pomocy C++Buildera nie zawiera żadnych informacji o tworzeniu apletów panelu
sterowania i zaledwie szczątkowe wiadomości o klasie TAppletApplication i
module CtlPanel, chociaż pewną rekompensatę stanowi opis zdarzeń klasy
TAppletModule. Można go uzyskać, naciskając klawisze Ctrl+F1 po wybraniu pola
danego zdarzenia na karcie Events inspektora obiektów.
Rysunek 8.8 Zdarzenia obiektu AppletModule1 w oknie inspektora obiektów
Większość dostępnych tu zdarzeń nie będzie w naszym przykładzie potrzebna. Jak
wiadomo, zdarzenia OnCreate i OnDestroy generowane sÄ… odpowiednio w momencie
utworzenia i zlikwidowania apletu, a także w chwili otwarcia i zamknięcia okna
Panelu sterowania. Należy pamiętać, że Panel sterowania komunikuje się z
apletem nie tylko w chwili jego wywołania (dwukrotnego kliknięcia ikony), lecz
również w czasie inicjalizacji (pobranie parametrów, jak ikona i opisy) i
zamknięcia. Związane są z tym zdarzenia OnInquire, OnNewInquire, OnStop i and
OnStartWParms. Nie będziemy ich tutaj używać, jednak warto zdawać sobie sprawę
z możliwości ich wykorzystania do wymiany danych.
W naszym przykładzie wykorzystamy natomiast zdarzenie OnActivate, generowane w
chwili dwukrotnego kliknięcia ikony apletu w oknie Panelu sterowania. Obiekt
Sender, przekazywany jako parametr funkcji obsługi zdarzenia, identyfikuje
wywoływany moduł (aplet logiczny). Drugi parametr funkcji, Data, zawiera
wskaźnik do struktury danych wykorzystywanej w obsłudze zdarzeń OnInquire i
OnNewInquire (dodatkowe informacje na temat odpowiednich komunikatów i
związanych z nimi struktur danych można znaleźć w rozdziale 24).
Projektujemy formularz apletu
Powróćmy obecnie do projektowania naszego apletu i zaprojektujmy dla niego
prosty formularz, zawierający trzy przyciski. Po wybraniu modułu apletu
(AppletModule1) w oknie eksploratora modułów, kliknij dwukrotnie pole
właściwości AppletIcon w oknie inspektora obiektów. Na ekranie pojawi się okno
edytora obrazków, umożliwiające wybranie ikony reprezentującej aplet w panelu
sterowania (można tu użyć ikony zdefiniowanej uprzednio za pomocą edytora
graficznego i zapisanej w pliku .ico). W polu właściwości Caption wpisz nazwę
apletu (np. "Aplet ćwiczebny"), a w polu właściwości Help
opis apletu (np.
"To jest aplet przykładowy").
Wybierz polecenie New Form z menu File i ustaw rozmiary nowoutworzonego
formularza poprzez przeciąganie krawędzi myszą lub wpisanie odpowiednich
wartości do pól Width i Height inspektora obiektów. Następnie wybierz z karty
Standard palety komponent TButton i wstaw go do formularza kliknięciem lewego
przycisku myszy. Powtórz tę operację trzykrotnie, nadając przyciskom
właściwości opisane w tabeli 8.4.
Tabela 8.4. Właściwości przycisków dla przykładowego apletu
Komponent
Właściwość
Wartość
Button1
Caption
Width
Pokaż pasek zadań
110
Button2
Caption
Width
Ukryj pasek zadań
110
Button3
Caption
Width
Zamknij
110
Utwórz funkcję obsługi zdarzenia OnClick dla przycisku Button1, klikając go
dwukrotnie i wpisując w oknie edytora następujący kod:
void __fastcall TForm2::Button1Click(TObject *Sender)
{
// Pokaż pasek zadań.
HANDLE Hide_TaskBar;
Hide_TaskBar = FindWindow("Shell_traywnd", "");
SetWindowPos(Hide_TaskBar, 0, 0, 0, 0, 0, SWP_SHOWWINDOW);
}
W analogiczny sposób utwórz funkcję obsługi zdarzenia OnClick dla przycisku
Button2. Jej kod powinien wyglądać następująco:
void __fastcall TForm2::Button2Click(TObject *Sender)
{
// Ukryj pasek zadań.
HANDLE Hide_TaskBar;
Hide_TaskBar = FindWindow("Shell_traywnd", "");
SetWindowPos(Hide_TaskBar, 0, 0, 0, 0, 0, SWP_HIDEWINDOW);
}
Pozostało nam do obsłużenia zdarzenie OnClick dla przycisku Button3.
Odpowiednia funkcja obsługi będzie miała postać
void __fastcall TForm2::Button3Click(TObject *Sender)
{
Close();
}
W następnej kolejności trzeba będzie zmodyfikować sposób tworzenia formularza.
C++Builder generuje kod automatycznie tworzÄ…cy formularz w chwili uruchomienia
aplikacji (załadowania pliku .cpl do pamięci). Ponieważ nie odpowiada to naszym
potrzebom, musimy usunąć domyślny kod i zastąpić go własnym, tworzącym
formularz dopiero w chwili wywołania apletu. W tym celu otwórz plik źródłowy
Project1.cpp w edytorze kodu, znajdź definicję funkcji DllEntryPoint() i usuń z
niej wywołanie
Application->CreateForm(__classid(TForm2), &Form2);
Następnie wywołaj okno eksploratora modułów (można to zrobić za pomocą
polecenia View|Forms lub naciśnięciem klawiszy Shift+F12), wybierz moduł
AppletModule1 i kliknij OK. W oknie inspektora obiektów kliknij dwukrotnie w
polu zdarzenia OnActivate, tworząc w ten sposób funkcję jego obsługi. Uzupełnij
ją następującym kodem:
void __fastcall TAppletModule1::AppletModuleActivate(TObject *Sender,
int Data)
{
// Utwórz formularz.
if(!Form2)
Form2 = new TForm2(this);
// Wyświetl formularz jako okno modalne i poczekaj
// na jego zamknięcie.
Form2->ShowModal();
// Usuń formularz.
delete Form2;
}
Wygląd okien IDE po zakończeniu projektowania pokazano na rysunku 8.9.
Rysunek 8.9. Gotowy projekt apletu
To już prawie wszystko, zatem pora zapisać nasz projekt. Wybierz polecenie Save
All z menu File i zapisz pliki projektu w wybranym przez siebie katalogu.
W razie potrzeby można nakazać C++Builderowi automatyczne przemianowanie
utworzonego pliku wynikowego i skopiowanie go do właściwego katalogu
systemowego. W tym celu wybierz okno eksploratora modułów i kliknij ikonę
modułu prawym przyciskiem myszy. Wyświetli to menu kontekstowe widoczne na
rysunku 8.10. Zawiera ono trzy opcje: Install Control Panel Applet (zainstaluj
aplet), Uninstall Control Panel Applet (odinstaluj aplet) i Launch Control
Panel (uruchom Panel sterowania). Wybranie polecenia Install Control Panel
Applet spowoduje skompilowanie kodu apletu i skopiowanie go do odpowiedniego
katalogu. Po wyświetleniu komunikatu o sukcesie możesz uruchomić Panel
sterowania poleceniem Launch Control Panel, co powinno wyświetlić okno
zawierającego ikonę naszego apletu. Jej dwukrotne kliknięcię wyświetli
formularz zdefiniowany przez nas wcześniej. Do zakończenia działania apletu
służy przycisk Zamknij (zobacz rysunek 8.11).
Rysunek 8.10 Menu kontekstowe eksploratora modułów umożliwia zainstalowanie lub
odinstalowanie apletu oraz uruchomienie Panelu sterowania
Rysunek 8.11 Przykładowy aplet w działaniu
Aplet można także uruchomić bez pośrednictwa Panelu sterowania, wydając
polecenie Uruchom z menu Start i wpisujÄ…c w oknie Uruchamianie:
rundll32 shell32.dll,Control_RunDLL project1.cpl @0
Wartość wpisana po znaku @ jest numerem apletu logicznego (okna dialogowego),
który ma być wywołany z załadowanego pliku .cpl. Aplety numerowane są od zera,
zatem @0 oznacza pierwszy aplet. W naszym przypadku jest on zarazem jedynym
apletem logicznym, toteż zapis @0 można pominąć. Gdyby plik .cpl zawierał dwa
aplety logiczne, do wywołania drugiego z nich należałoby użyć polecenia
rundll32 shell32.dll,Control_RunDLL mycpl.cpl @1
Użyty tu mechanizm jest dość prosty
program rundll32.exe odwołuje się do
biblioteki dynamicznej shell32.dll, a konkretnie
do zawartej w niej funkcji
Control_RunDLL(), obsługującej wywołanie i wymianę danych z określonym apletem
logicznym. Metodę tę można wypróbować również dla innych apletów, pamiętając
przy tym, że niektóre pliki .cpl zawierają pojedyncze aplety logiczne, inne

kilka apletów (co pociąga za sobą konieczność podania parametru @n). Warto
zdawać sobie sprawę z jej istnienia, chociaż jest ona tylko mniej wygodną
alternatywą dla użycia Panelu sterowania [1 Warto zwrócić uwagę na brak spacji
przed nazwą funkcji Control_RunDLL; w niektórych przypadkach użycie spacji
powoduje problemy z wywoÅ‚aniem funkcji ­­
przyp. tłum.].
Aplety panelu sterowania
podsumowanie
Klasyczna metoda tworzenia apletów Panelu sterowania może być dość uciążliwa,
wymaga bowiem każdorazowej zmiany rozszerzenia nazwy pliku i kopiowania go do
katalogu System lub System32. Również sam Panel sterowania może niekiedy
sprawiać nam kłopoty, blokując plik apletu i nie pozwalając go usunąć.
Narzędzia dostępne w C++Builderze, w tym kreator apletów, zwalniają programistę
z większości tych obowiązków, znacząco ułatwiając tworzenie i testowanie
apletów.


Wyszukiwarka