Biblioteka SeggerSTemWin w praktyce (2): menadżer okien

W drugim artykule dotyczącym biblioteki STemWin opisujemy podstawy obsługi menadżera okien. Zawarto w nim krótki opis wybranych funkcji API oraz przykładowe aplikacje wykorzystujące przedstawione dotąd wiadomości.

Fot. 1. Zestaw STM32F429I-Discovery i uruchomiona aplikacja demonstracyjna

Biblioteka STemWin jest dość dobrze rozbudowana pod względem liczby komponentów, funkcji API oraz innych ciekawych możliwości. Stąd też nie sposób jej opisać na kilku stronach bez podawania przykładówmających na celu zapoznanie czytelnika ze szczegółami i pozwolenia mu uniknąć ewentualnych problemów z jej zastosowaniem. Przedstawiamy podstawowe wiadomości na temat menedżera okien oraz opisujemy jego API.

Menedżer okien

Biblioteka STemWin oferuje przede wszystkim szeroką gamę komponentów interfejsu graficznego (widżety) oraz bogatą listę operacji (procedury)jakie można na nich wykonywać, jednakże trudno byłoby uzyskać sprawną i efektywną pracę aplikacji graficznej bez obecności pewnego mechanizmu zarządzania tymi obiektami. Przykładowo, nasza pierwsza prosta aplikacja graficzna [2] zawierała trzy położeniowo-statycznei nienakładające się na siebie widżety(oknogłówne, napisy oraz przyciski), a także korzystała z kilku procedur zmiany czcionki oraz koloru tekstu. Co się jednak stanie, gdy dodamy widżety dynamiczne, takie jak lista rozwijana i menu albo stworzymy inne okna globalne lub lokalne (w zakresie innych okien)?

Z pomocą przyjdzie nam menedżer okien (ang. window manager, WM) i w tym miejscu musimy zapamiętać, że wszystko co pojawia się na wyświetlaczu jest „zawarte” w pewnym oknie – prostokątnym obszarze ekranu o dowolnych wymiarach i położeniu. Na ekranie może być wiele takich okien i mogą one częściowo lub całkowicie przesłaniać inne okna (rysunek 2). Do ich utworzenia, przemieszczania, zmiany rozmiarów i innych manipulacji wykorzystywane są procedury dostarczane przez menedżera okien, który jest również odpowiedzialny zaniskopoziomową obsługę w postaci zarządzania warstwami tych okien oraz informowania aplikacji użytkownika o zmianach jakie powinny zostać wyświetlone [1].

 

Rys. 2. Możliwość wyświetlania wielu okien na przykładzie widżetów FRAMEWIN

 

Przed przystąpieniem do szczegółowego omawiania biblioteki STemWin warto zapoznać się z definicjami podstawowych wyrażeńco ułatwi zrozumienie jej opisu:

  • aktywne okno (ang. activewindow) – okno nad którym aktualnie są przeprowadzane operacje rysowania. Niekoniecznie musi to być okno położone najwyżej (topmost) – patrz pozycja Z.
  • funkcje zwrotne (ang. callbackroutines) – funkcje zdefiniowane w programie użytkownika, pozwalające wywoływać inne specyficzne funkcje w zależności od zarejestrowanego zdarzenia. Zwykle są one wykorzystywane do automatycznego przerysowania okna w przypadku wystąpienia zmiany ich zawartości.
  • obszar klienta (ang. clientarea) – jest to powierzchnia użytkowa okna na której można swobodnie umieszczać inne obiekty. Jeżeli okno zawiera ramkę lub pasek tytułowy to obszar klienta znajduje się w wewnętrznym prostokątnym polu. Jeśli natomiast brak jest takich dodatkowych ozdobników to współrzędne obszaru klienta zgadzają się ze współrzędnymi samego okna.
  • okno potomne (dziecko), okno rodzica (rodzic), rodzeństwo (ang. child/parentwindows, siblings)– okno potomne jest zdefiniowane względem innego okna – rodzica. Jeżeli okno rodzica przemieszcza się to jego okna potomne naśladują ruch w tym samym kierunku. W przypadku, gdy to okno potomne przemieszcza się względem okna rodzica w ten sposób, że jego część „wychodzi” poza obszarrodzica to zostanie ono przycięte. Okna potomne mające tego samego rodzica nazywane są rodzeństwem.
  • okno pulpitu (pulpit) (ang. desktop window) – najniżej położone (bottommost) okno tworzone automatycznie przez WM i całkowicie pokrywające obszar wyświetlacza. Wszystkie pozostałe okna są potomkami pulpitu, a jeśli brak jest takowych to pulpit domyślnie jest oknem aktywnym.
  • pozycja Z (współrzędna Z), spód i wierzch (dno i powierzchnia) (ang. Z-position, bottom/top) – każde utworzone okno oprócz dwóch współrzędnych (X,Y) posiada również trzecią, tak zwaną pozycję Z lub współrzędną głębokości (wirtualny trzeci wymiar), która określa położenie okna w stosunku do pozostałych okien rodzeństwa, poczynając od spodu i kończąc na wierzchu. W wyniku tego, okna mogą pojawiać się nad innymi lub pod nimi. Przełożenie okna na dno jest równoważne umieszczeniu go pod spodem innych okien rodzeństwa (o ile istnieją), a przełożenie okna na powierzchnię – umieszczeniu nad nimi. Domyślnie każde tworzone okno jest umieszczane na wierzchu, jeżeli nie podano innej flagi tworzenia (flagi kreacji).
  • przezroczystość (ang. transparency) – okno z włączoną funkcją przezroczystości zawiera obszary, które nie są przerysowywane razem z pozostałą częścią okna. Stąd też zachowują się one tak jak gdyby przepuszczały wszystko co znajduje się „za nimi”. Jednocześnie należy mieć na uwadze, aby okna znajdujące się „za” były przerysowane w pierwszej kolejności, a dopiero potem samo okno posiadające obszary przezroczyste. WM automatycznie obsługuje przerysowywanie w poprawnej kolejności.
  • przycinanie i obszar przycięty (ang. clipping, clip area) – przycinanie to proces ograniczenia widoczności okna lub jego części, aobszar przycięty to tylko widoczna jego część. Inaczej rzecz biorąc, obszar przycięty może być traktowany jako pełne okno minus obszar przesłonięty przez rodzeństwo o wyższej wartości współrzędnej Z minus ta część okna, która nie zawiera się w obszarze okna rodzica.
  • uchwyt (ang. handle) – unikalny identyfikator nadawany przez WM po utworzeniu okna. Dzięki niemu można wykonywać operacje na już istniejącym oknie.
  • ukrywanie i uwidacznianie okien (ang. hiding/showingwindows) – domyślnie wszystkie utworzone okna są ukryte jeżeli nie podano stosownej flagi kreacji Innymi słowy, utworzone okna istnieją i mają uchwyt, a za pomocą odpowiednich procedur WM można je pokazywać i ponownie ukrywać.
  • współrzędne (ang. coordinates) – są to zazwyczaj 2-wymiarowe współrzędne wyrażone w jednostkach pikseli. Pierwsza wartość określa położenie w osi poziomej (współrzędna x), a druga – w osi pionowej (współrzędna y).
  • współrzędne okna (ang. windowcoordinates) – współrzędne powiązane z danym oknem. Górny lewy róg (początek) okna posiada współrzędne (0,0).
  • współrzędne okna rodzica (ang. parentcoordinates) – współrzędne powiązane z oknem rodzica. Górny lewy róg (początek) okna posiada współrzędne (0,0).
  • współrzędne pulpitu (ang. desktop coordinates) – współrzędne powiązane z oknem pulpitu. Górny lewy róg (początek) ekranu posiada współrzędne (0,0).
  • zatwierdzanie i unieważnianie okna (ang. validation/invalidation) –zatwierdzone okno to takie, które jest wpełni zaktualizowane inie potrzebuje przerysowania, a unieważnione okno nie odzwierciedla jeszcze wprowadzonych w nim zmian i musi być przerysowane całkowicie lub częściowo. W sytuacji gdy w oknie dokonały się zmiany to WM oznacza je jako unieważnione i dopiero po kolejnym przerysowaniu (wywołanym ręcznie lub w ramach funkcji zwrotnej) zostanie ono zatwierdzone.

Menedżer okien (WM), jak już wspomniano, oferuje procedury do manipulowania oknami oraz przeprowadzania innych powiązanych z nimi operacji.Tabela 1 przedstawia na początek wybrane z nich – szczegółowe informacje na temat przyjmowanych parametrów i zwracanych wartości każdej z nich można znaleźć w rozdziale „The Window Manager” dokumentacji biblioteki (w tym miejscu i przy omawianiu widżetów ograniczono się do przedstawienia jedynie krótkiego opisu procedur).

Tab. 1. Wybrane procedury menedżera okien

Procedura

Opis

WM_Activate() Uruchamia menedżera okien (WM). Domyślnie jest on uruchomiony po inicjalizacji biblioteki.
WM_AttachWindow() Przywiązuje okno do wskazanego rodzica. Jeżeli wskazane okno należy już do innego okna rodzica to jest ono najpierw odwiązywane, a pozycja we współrzędnych okna rodzica jest zachowywana. Jeśli natomiast parametr uchwytu do okna rodzica ma wartość 0 to okno pozostaje nieprzywiązane.
WM_AttachWindowAt() Tak jak powyżej, ale z nową pozycją okna we współrzędnych rodzica.
WM_BringToBottom() Przenosi okno pod spód (za rodzeństwem).
WM_BringToTop() Przenosi okno na wierzch (przed rodzeństwem).
WM_ClrHasTrans() Wyłącza funkcję przezroczystości dla okna (zeruje flagę hastransparency).
WM_CreateWindow() Tworzy okno o danych wymiarach w zadanej pozycji i zwraca uchwyt do niego.
WM_CreateWindowAsChild() Tak jak powyżej, ale okno będzie potomkiem innego wskazanego okna.
WM_Deactivate() Zatrzymuje menedżera okien (WM). Funkcje zwrotne nie są już wywoływane.
WM_DeleteWindow() Usuwa wskazane okno oraz zawarte w nim widżety (okna potomków) jeżeli istnieją.
WM_DetachWindow() Odwiązuje okno potomka od okna rodzica, przy czym w wyniku tej operacji WM nie będzie przerysowywał pierwszego.
WM_DisableWindow() Przełącza okno w stan zablokowany i blokuje wysyłanie powiadomień od urządzeń wskazujących (dotyk, myszka, joystick) do takiego okna.
WM_EnableWindow() Przełącza okno w stan odblokowany (stan domyślny) i zezwala na wysyłanie powiadomień od urządzeń wskazujących do takiego okna.
WM_GetActiveWindow() Zwraca uchwyt do aktywnego okna.
WM_GetClientWindow() Zwraca uchwyt do okna klienta – procedura często stosowana w przypadku widżetu FRAMEWIN.
WM_GetDesktopWindow() Zwraca uchwyt do pulpitu.
WM_GetDesktopWindowEx() Zwraca uchwyt do wybranego pulpitu w środowisku wielowarstwowym.
WM_GetFirstChild() Zwraca uchwyt do pierwszego okna potomka w oknie rodzica lub 0 jeśli takowych nie ma. Pierwsze okno dziecko to takie, które znajduje się pod spodem innych okien z rodzeństwa.
WM_GetFocussedWindow() Zwraca uchwyt do zaznaczonego okna lub 0 jeśli takiego nie ma.
WM_GetHasTrans() Zwraca stan flagihastransparencyokna (funkcja przezroczystości): 0 – wyzerowana, 1 – ustawiona.
WM_GetId() Zwraca numer identyfikacyjny widżetu lub 0 jeśli nie jest to widżet.
WM_GetNextSibling() Zwraca uchwyt do następnego okna w rodzeństwie lub 0 jeśli takowego nie ma. Kolejne okno posiada wartość pozycji Z o jeden większą od aktualnego okna przekazanego jako parametr.
WM_GetOrgX() Zwraca pozycję górnego lewego rogu aktywnego okna w osi X układu współrzędnych pulpitu.
WM_GetOrgY() Zwraca pozycję górnego lewego rogu aktywnego okna w osi Yukładu współrzędnych pulpitu.
WM_GetParent() Zwraca uchwyt do okna rodzica lub 0 jeśli nie istnieje (przypadek pulpitu).
WM_GetPrevSibling() Zwraca uchwyt do poprzedniego okna w rodzeństwie lub 0 jeśli takowego nie ma. Poprzednie okno posiada wartość pozycji Z o jeden mniejszą od aktualnego okna przekazanego jako parametr.
WM_GetStayOnTop() Zwraca stan flagistay on topokna: 0 – wyzerowana, 1 – ustawiona.
WM_GetWindowSizeX() Zwraca wymiar okna w osi X (szerokość).
WM_GetWindowSizeY() Zwraca wymiar okna w osi Y (wysokość).
WM_HasFocus() Zwraca 1 jeśli okno jest zaznaczone, a 0 – w przeciwnym wypadku.
WM_HideWindow() Ukrywa okno – w rzeczywistości stanie się ono ukryte dopiero po  przerysowaniu innych okien znajdujących się za nim.
WM_IsCompletelyCovered() Zwraca 1 jeśli okno jest całkowicie przesłonięte, a 0 – w przeciwnym wypadku.
WM_IsCompletelyVisible() Zwraca 1 jeśli okno jest całkowicie widoczne, a 0 – w przeciwnym wypadku.
WM_IsEnabled() Zwraca 1 jeśli okno jest w stanie odblokowanym, a 0 – w przeciwnym wypadku.
WM_IsVisible() Zwraca 1 jeśli okno jest widoczne, a 0 – jeśli ukryte.
WM_IsWindow() Zwraca 1 jeśli przekazany parametr to poprawny uchwyt do okna, a 0 – w przeciwnym wypadku.
WM_MoveChildTo() Przesuwa okno potomka do wskazanejpozycji we współrzędnych okna rodzica.
WM_MoveTo() Przesuwa okno do wskazanejpozycji we współrzędnych pulpitu.
WM_MoveWindow() Przesuwa okno o zadane wartości przesunięć.
WM_Paint() Rysuje lub przerysowuje okno natychmiast z chwilą wywołania.
WM_PaintWindowAndDescs() Przerysowuje okno i jego potomków.
WM_ResizeWindow() Zwiększa lub zmniejsza wymiary okna na podstawie przekazanych wartości ze znakiem.
WM_SetDesktopColor() Ustawia nowy kolor pulpitu i zwraca kolor poprzedni. Bez wywołania tej procedury pulpit nie będzie przerysowywany i w wyniku tego usunięte okna będą nadal widoczne.
WM_SetDesktopColorEx() Ustawia nowy kolor wybranego pulpitu w środowisku wielowarstwowym i zwraca kolor poprzedni.
WM_SetFocus() Zaznacza wybrane okno.
WM_SetHasTrans() Włącza funkcję przezroczystości dla okna.
WM_SetId() Ustawia nowy numer identyfikacyjny widżetu.
WM_SetSize() Ustawia nowe wymiary okna.
WM_SetWindowPos() Ustawia nową pozycję i wymiary okna.
WM_SetXSize() Ustawia nowy wymiar okna w osi X.
WM_SetYSize() Ustawia nowy wymiar okna w osi Y.
WM_SetStayOnTop() Ustawia (1) lub zeruje (0) flagęstay on topokna.
WM_ShowWindow() Uwidacznia okno – w rzeczywistości będzie ono widoczne dopiero po jego przerysowaniu.
WM_Update() Przerysowuje unieważnioną część okna, które zostaje następnie zatwierdzone.
WM_UpdateWindowAndDescs() Przerysowuje unieważnione części okna i jego potomków.

Większość wymienionych powyżej procedurprzyjmuje jako pierwszy parametr typu WM_HWIN, który jest ściśle związany z uchwytem do okna (może to być również uchwyt do widżetu, np. <NazwaWidżetu>_Handler). Typ (zazwyczaj jest to int przy podawaniu liczb) i znaczenie kolejnych parametrów są niejako wskazywane przez samą nazwę procedury. Oto przykłady:

  • WM_AttachWindow(hWidget, hWindow) – odwiązuje okno hWidget od poprzedniego okna rodzica i przywiązuje go do okna hWindow z zachowaniem pozycji we współrzędnych poprzedniego okna rodzica,
  • WM_GetWindowSizeX(hWindow) – zwracaszerokość okna, a jeżeli uchwyt ma wartość 0 to zostanie zwrócona szerokość pulpitu,
  • WM_MoveTo(hWindow, 15, 20) –przesuwa okno, przy czym jego lewy górny róg będzie znajdował się w punkcie (15,20),
  • WM_MoveWindow(hWindow, 15, -20) – przesuwa okno o 15 pikseli w prawo i 20 pikseli w górę,
  • WM_ResizeWindow(hWindow, 15, -20) – zwiększa wymiar okna w osi X o 15 pikseli oraz zmniejsza o 20 pikseli w osi Y,
  • WM_SetFocus(hWindow) – zaznaczenie okna można pokazać na przykładzie widżetu FRAMEWIN, który posiada pasek tytułowy (rysunek 2). Jeżeli wcześniej pasek ten miał kolor szary to zaznaczenie powiązanego z nim okna spowoduje zmianę koloru na niebieski,
  • WM_SetSize(hWindow, 100, 50) – zmienia wymiary okna odpowiednio na szerokość 100 i wysokość 50,
  • WM_SetWindowPos(hWindow, 100, 50, 10, 5) – jak powyżej z tą różnicą, że umieszcza początek okna w punkcie (10,5) układu współrzędnych pulpitu,
  • WM_ShowWindow(hWindow) – uwidacznia okno, ale dopiero wykonanie procedury WM_Exec() lub jawne wywołanie WM_Paint() spowoduje jego pojawienie się na ekranie (podobna zasada obowiązuje podczas ukrywania okna, przy czym przerysowywane są inne widoczne okna).

Rys. 3. Efekt wywołania funkcji WM_SetFocus() na przykładzie widżetu FRAMEWIN

Po lewej okno niezaznaczone, a po prawej – zaznaczone

 

Przy okazji warto również zapoznać się z flagami kreacji, które mogą zostać wykorzystane w procedurach tworzącychzarówno okna jak i widżety (tabela 2). Najczęściej wykorzystywana będzie flaga WM_CF_SHOW, która pozwala na natychmiastowe wyświetlenie okna (oczywiście zaraz po jego przerysowaniu). Flagi zakotwiczenia mają znaczenie w przypadku, gdy zmieniają się wymiary okna rodzica, tzn. wielkość odległości wybranej krawędzi nowego okna potomka od odpowiadającej jej krawędzi okna rodzica będzie utrzymywana na stałe – zobrazowano to na jednym z poniższych listingów.

Tab. 2. Wybrane flagi kreacji łączone operatorem OR

Flaga kreacji Opis

WM_CF_ANCHOR_BOTTOM

Zakotwicza dolną krawędź nowego okna do dolnej krawędzi okna rodzica.

WM_CF_ANCHOR_LEFT

Zakotwicza lewą krawędź nowego okna do lewej krawędzi okna rodzica (konfiguracja domyślna).

WM_CF_ANCHOR_RIGHT

Zakotwicza prawą krawędź nowego okna do prawej krawędzi okna rodzica.

WM_CF_ANCHOR_TOP

Zakotwicza górną krawędź nowego okna do górnej krawędzi okna rodzica (konfiguracja domyślna).

WM_CF_BGND

Umieszcza nowe okno pod spodem istniejących.

WM_CF_FGND

Umieszcza nowe okno na wierzchu istniejących (konfiguracja domyślna).

WM_CF_HASTRANS

Włącza funkcję przezroczystości. Opcja przydatna dla okien, które nie mają całkowicie wypełnionych obszarów klienta.

WM_CF_HIDE

Ukrywa nowe okno (konfiguracja domyślna).

WM_CF_SHOW

Uwidacznia nowe okno.

WM_CF_STAYONTOP

Gwarantuje, że nowe okno będzie znajdować się zawsze na wierzchu jeśli inne okna nie mają ustawionej flagistay on top.

Pierwszy przykład demonstruje przesuwanie zaznaczonego okna (rysunek 2):

 

Rys. 4. Widżet FRAMEWIN ze zmieniającymi się wymiarami

Drugi przykład ilustruje dynamiczną zmianę wymiarów okna (rysunek 4):

Jan Szemiet

 

Literatura:

[1] UM03001: emWin, Graphic Library with Graphical User Interface, User & Reference Guide

[2] LINK – Biblioteka STemWin: Pierwsza prosta aplikacja okienkowa

Do pobrania

Autor: admin

Admin