Statusbar
Wiele aplikacji posiada na dole taki fajny pasek zwany '''Statusbar'''em albo paskiem statusu. Programy wykorzystują go do wyświetlania różnych, zwykle mało przydatnych informacji. Jeżeli chcesz zobaczyć przykład Statusbara to spójrz na sam dół okna przeglądarki, a zapewne go tam znajdziesz. Jeżeli masz wyjątkowego pecha i go tam nie ma to zawsze możesz spojrzeć tutaj:
Tworzenie Statusbar'a
Co może się wydać dziwne początkującym, Statusbar jest kontrolką. I to w dodatku z grupy ''Common Controls'' więc należy pamiętać o dolinkowaniu odpowiedniej biblioteki. Na początku inicjujemy kontrolki funkcją
InitCommonControlsEx:
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof( INITCOMMONCONTROLSEX );
icc.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx( & icc );
Teraz możemy utworzyć Statusbar. Tworzymy go tak samo jak inne kontrolki - funkcją
CreateWindowEx. Nazwa klasy to
STATUSCLASSNAME. Zauważ, że jest to nazwa stałej reprezentująca nazwę klasy:
HWND hStatusBar = CreateWindowEx( 0, STATUSCLASSNAME, NULL, SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE
, 0, 0, 0, 0, hwnd,( HMENU ) 200, hInstance, NULL );
Wymiary oraz położenie okna ustawiliśmy na
0, ponieważ system automatycznie ustawi nasz pasek statusu na dole okna - jest to jedna z niewielu rzeczy, które Windows robi za nas. Użyliśmy też stylu
SBARS_SIZEGRIP. Wszystkie style zostały zebrane w poniższej tabelce (jak widać nie ma ich zbyt wiele):
Zawartość Statusbar'a
Zanim wpiszemy jakiś tekst do paska statusu, trzeba powiedzieć nieco o jego budowie. Mianowicie składa się on z kilku części (max
256), a każda z nich może wyświetlać różny tekst i ewentualnie także ikonkę. Na początku trzeba ustalić ile części chcemy mieć. Oczywiście będziemy mogli później zmieniać ilość części. A można to zrobić wysyłając komunikat
SB_SETPARTS. W parametrze
wParam wstawiamy ilość części, a w
lParam wskaźnik to tablicy liczb
int. Liczby te oznaczają długości kolejnych części statusbar'a. Jeśli wartością jest
-1, system sam sobie dobierze szerokość z tego co zostało ;-). Oto przykład:
int iStatusBarWidths[] = { 200, 300, - 1 };
SendMessage( hStatusBar, SB_SETPARTS, 3,( LPARAM ) iStatusBarWidths );
Trzeba jeszcze wspomnieć o pułapce, w którą wpadają amatorzy Statusbarów:
Szerokości, których używamy przy SB_SETPARTS nie oznaczają prawdziwej szerokości fragmentu StatusBara ale odległość jego końca od lewej strony.
|
Jak zwykle programiści Microsoftu znowu dali upust swojemu niezwykłemu talentowi w tworzeniu beznadziejnego API. Wystarczy narzekania - zobaczmy co to wszystko oznacza w praktyce:
Skoro już dostatecznie się natrudziliśmy przy dzieleniu StatusBara na części, wypełnijmy go treścią. Możemy to zrobić za pomocą komunikatu
SB_SETTEXT. W parametrze
wParam podajemy index (numer liczony od
0) części, w której ustawiamy tekst, a w
lParam sam tekst:
SendMessage( hStatusBar, SB_SETTEXT, 2,( LPARAM ) "To jest mój własny StatusBar !!!" );
A oto efekt naszych działań:
Czasami zachodzi potrzeba pobrania tekstu ze StatusBara. Standardowo służy do tego odpowiedni komunikat czyli
SB_GETTEXT. Wcześniej jednak musimy pobrać rozmiar bufora (komuniakt
SB_GETTEXTLENGTH). Oto przykład:
DWORD dlugosc = SendMessage( hStatusBar, SB_GETTEXTLENGTH, 2, 0 );
LPSTR Bufor =( LPSTR ) GlobalAlloc( GPTR, dlugosc + 1 );
SendMessage( hStatusBar, SB_GETTEXT, 2,( LPARAM ) Bufor );
GlobalFree( Bufor );
Komunikat
SB_GETTEXTLENGTH w parametrze
wParam przyjmuje index części StatusBara, której długość tekstu chcemy poznać. Tak samo jest w przypadku
SB_GETTEXT, tylko ten dodatkowo w parametrze
lParam przyjmuje adres bufora, do którego ma zapisać tekst.
Ikonki
Wiele "profesjonalnych" aplikacji ma w swoich StatusBarach ikonki. Jeżeli chcemy by nasze programy także posiadały zaszczytny tytuł "profesjonalnych" powinniśmy je w takie ikonki wyposażyć. Na nasze szczęście nie wymaga to żadnych dodatkowych zabiegów i sprowadza się do odpowiednich komunikatów. Tak więc do dzieła!
Ikonkę można ustawić za pomocą komunikatu
SB_SETICON. Parametr
wParam to tradycyjnie index części, natomiast
lParam to uchwyt do ikony. Najpierw trzeba jednak załadować ikonę:
HICON hIcon =( HICON ) LoadImage( hInstance, MAKEINTRESOURCE( 100 )
, IMAGE_ICON, 16, 16, LR_SHARED | LR_LOADTRANSPARENT );
Zauważ, że użyliśmy funkcji
LoadImage zamiast
LoadIcon. A to dlatego, że funkcja
LoadIcon ładuje ikonę o wymiarach
32x32 a nie pasującym do StatusBara
16x16. Po prostu StatusBar nie skaluje ikon, więc gdybyśmy użyli funkcji
LoadIcon to w StatusBarze pojawił by się jedynie wycinek ikony, co jest efektem raczej niepożądanym ;-)
Skoro mamy już ikonę o odpowiednich rozmiarach, możemy już wysłać omówiony wcześniej komunikat:
SendMessage( hStatusBar, SB_SETICON, 1,( LPARAM ) hIcon );
A oto nasz StatusBar z ikonką:
Tooltipy
StatusBar możemy łatwo wyposażyć w tooltipy. Podobnie jak z większością rzeczy w WinAPI służą do tego odpowiednie komunikaty. W tym przypadku jest to
SB_SETTIPTEXT. W parametrze
wParam wstawiamy index części a w
lParam tekst:
SendMessage( hStatusBar, SB_SETTIPTEXT, 1,( LPARAM ) "Odśwież" );
Żeby nasz tooltip się pojawił, musimy użyć stylu
SBT_TOOLTIPS przy tworzeniu kontrolki. I to tyle. Nasz tooltip działa:
Komunikaty
Choć zazwyczaj gdy klikamy na StatusBar nic się nie dzieje, to wcale nie znaczy, że tak musi być. Gdy użytkownik kliknie na StatusBarze do okna-rodzica wysyłane są odpowiednie powiadomienia. Oto kilka z nich:
Od każdego z powyższych powiadomień otrzymujemy strukturę
NMMOUSE. Oto niektóre parametry:
Warto zwrócić uwagę na to, że
NMMOUSE może pochodzić od różnych kontrolek, nie tylko StatusBar'a, dlatego znaczenie pól
dwItemSpec i
dwItemData może być inne niż w tabelce powyżej. Oto przykład obsługi takiego powiadomienia:
case WM_NOTIFY:
switch((( LPNMHDR ) lParam )->code ) {
case NM_CLICK:
if((( LPNMHDR ) lParam )->hwndFrom == hStatusBar ) {
char buf[ 20 ];
itoa(((( LPNMMOUSE ) lParam )->dwItemSpec ), buf, 10 );
MessageBox( hwnd, buf, "Index:", MB_ICONINFORMATION );
}
break;
}
break;
Zmiana rozmiaru okna
Potrafimy już stworzyć StatusBar z (prawie) wszystkimi bajerami i w sumie można by na tym zakończyć ten artykuł, gdyby nie jeden bardzo poważny problem. Mianowicie, gdy zmieniamy rozmiar okna programu to StatusBar zostaje na swoim starym miejscu zamiast się ładnie dopasować do okna! Niestety o to dopasowanie musimy zadbać my sami.
A oto i proste rozwiązanie tego skomplikowanego problemu: wystarczy, że obsłużymy komunikat
WM_SIZE w ten sposób:
SendMessage( hStatusBar, WM_SIZE, 0, 0 );
Po prostu wysyłamy komunikat
WM_SIZE do StatusBara. Nie są potrzebne żadne parametry. Trzeba mu "przypomnieć", że rozmiar okna został zmieniony i musi się on dopasować do niego na nowo.