[2] Bezpłatna biblioteka graficzna Microchip Graphics Library dla mikrokontrolerów PIC24 i PIC32: przykłady
Pierwszą część artykułu opublikowaliśmy kilka dni temu, w drugiej przedstawiamy kolejne warstwy bibliotek graficznych firmy Microchip oraz dynamicznych elementów graficznych. Dzięki temu, ze bazujemy na przykładach, prezentowany wykład ma niezwykle praktyczny charakter.
Warstwa Object Layer
Poprzednio opisane funkcje rysowania podstawowych elementów graficznych łącznie z wyświetlaniem tekstu nie są zbyt trudne do napisania dla średnio zaawansowanego programisty. A jeszcze ważniejsze jest to, że ich implementacja nie jest bardzo czasochłonna, poza ręcznym definiowaniem wzorców znaków alfanumerycznych. Ale warstwa Pirimitive Layer to wstęp do prawdziwych możliwości biblioteki ukrytych w warstwie obiektów Object Layer. Zawiera ona wiele bardziej lub mniej skomplikowanych elementów graficznych zwanych obiektami lub widżetami. W obecnie dostępnej wersji biblioteki są dostępne następujące obiekty:
- Button – przycisk, który może być w 3 stanach: przyciśnięty, zwolniony i zablokowany. Każdy ze stanów ma swój zdefiniowany kolor w strukturze GOL_SCHEME.
- Chart – element wykorzystywany do graficznego przedstawiania wielkości w formie trójwymiarowych słupków, lub procentowego podziału okręgu (rysunek 9).
Rys. 9. Przykładowe skutki działania obiektu Chart
- Check Box – pole wyboru.
- Radio Button – przyciski opcji.
- Round Dial – wirtualne pokrętło.
- Digital Meter – cyfrowe wyświetlanie wartości.
- Edit Box – obiekt przeznaczony do wprowadzania tekstu.
- List Box – obiekt do wybierania elementów z listy.
- Meter – obiekt przeznaczony do wyświetlania wielkości w formie analogowej skali.
- Slider/Scroll Bar – obiekt w formie „suwaka” przeznaczony do ustawiania wartości.
- Static Text – przeznaczony do wyświetlania komunikatów tekstowych.
- Text Entry – klawiatura do wprowadzania znaków alfanumerycznych.
- Window – wyświetlanie okna.
Każdy taki obiekt ma zdefiniowany nagłówek w formie struktury OBJ_HEADER (listing 5).
List. 5. Struktura nagłówka definująca obiekty
typedef struct { WORD ID; void * pNxtObj; GOL_OBJ_TYPE type; WORD state; SHORT left; SHORT top; SHORT right; SHORT bottom; GOL_SCHEME * pGolScheme; DRAW_FUNC DrawObj; FREE_FUNC FreeObj; MSG_FUNC MsgObj; MSG_DEFAULT_FUNC MsgDefaultObj; } OBJ_HEADER;
Składowe left, right, top i bottom nagłówka OBJ_HEADER określają współrzędne pozycji obiektu i rozmiar. Bardzo ważną składową struktury nagłówka jest struktura stylu GOL_SCHEME. Funkcja GOLCreateScheme () tworzy i inicjalizuje tę strukturę określającą styl obiektów graficznych tworzonych w warstwie Graphic Objet Layer. Na rysunku 10 pokazano przykład znaczenia składowych struktury GOL_SCHEME dla obiektu przycisku Button.
Rys. 10. Składowe struktury stylu na przykładzie obiektu Button
Składowe EmbossDkColor i EmbossLtColor definiują kolory wykorzystywane dla uzyskania efektu przestrzennego przycisku. Color1 jest kolorem przycisku w stanie „nie przyciśnięty”, a Color0 jest kolorem przycisku „przyciśnięty”. Kiedy przycisk jest w stanie zablokowanym (disabled), to przebarwia się na kolor zdefiniowany w składowej TextColorDisabled. Całkowite ukrycie przycisku jest możliwe kiedy zdefiniujemy CommonBkColor taki sam jak kolor tła. Składowa *pFont jest wskaźnikiem na bufor zawierający tekst wyświetlany na przycisku. Kolor tego tekstu jest określany składowymi TextColor0 (przycisk wciśnięty) i TextColor1 (przycisk zwolniony).
Składowa DRAW_FUNC jest wskaźnikiem do funkcji rysowanego obiektu, FREE_FUNC wskaźnikiem do funkcji zwalniania obiektu, a MSG_FUNC do funkcji wysyłani komunikatów. Przykładowy obiekt Button jest tworzony przez funkcję *BtnCreate. Fragment tej funkcji jest pokazany na listingu 6.
List. 6. Fragment funkcji tworzenia obiektu przycisku
BUTTON *BtnCreate ( WORD ID, SHORT left, SHORT top, SHORT right, SHORT bottom, SHORT radius, WORD state, void *pBitmap, XCHAR *pText, GOL_SCHEME *pScheme ) { BUTTON *pB = NULL; pB = (BUTTON *)GFX_malloc(sizeof(BUTTON)); if(pB == NULL) return (NULL); pB->hdr.ID = ID; // unique id assigned for referencing pB->hdr.pNxtObj = NULL; // initialize pointer to NULL pB->hdr.type = OBJ_BUTTON; // set object type pB->hdr.left = left; // left position pB->hdr.top = top; // top position pB->hdr.right = right; // right position pB->hdr.bottom = bottom; // bottom position pB->radius = radius; // radius pB->pBitmap = pBitmap; // location of bitmap pB->pText = pText; // location of the text pB->hdr.state = state; // state pB->hdr.DrawObj = BtnDraw; // draw function pB->hdr.MsgObj = BtnTranslateMsg; // message function pB->hdr.MsgDefaultObj = BtnMsgDefault; // default message function pB->hdr.FreeObj = NULL; // free function // Set the color scheme to be used if(pScheme == NULL) pB->hdr.pGolScheme = _pDefaultGolScheme; else pB->hdr.pGolScheme = (GOL_SCHEME *)pScheme; pB->textWidth = 0; pB->textHeight = 0; if(pB->pText != NULL) { BtnSetText(pB, pText); }
Jeżeli chcemy utworzyć własny przycisk o nazwie na przykład BUTTON1, to wywołujemy tą funkcję wymaganymi argumentami na przykład tak jak to zostało pokazane na listingu 7.