Własne klasy obsługujące podstawowe kontrolki WinApi
Stronę tą wyświetlono już: 1750 razy
Sporą wadą WinApi jest fakt, że obsługa kontrolek wymaga znajomości wielu funkcji obsługi okien oraz komunikatów i styli wpływających na wygląd tychże kontrolek. Nie ma tutaj również mowy o obiektowym tworzeniu kontrolek. Można jednak samemu napisać sobie klasy, które umożliwią łatwe obsłużenie tworzenia kontrolek, sterowania ich zachowaniem oraz wyglądem. Z tego właśnie powodu utworzyłem sobie mały zbiór klas, które umożliwiają mi dynamiczne tworzenie kontrolek oraz łatwy dostęp do opcji nimi sterujących oraz możliwość podpinania obiektów klas odpowiedzialnych za realizację zadań wywoływanych przez notyfikacje wysyłane przez daną kontrolkę do okna rodzica.
Oto lista klas do obsługi podstawowych kontrolek:
- WndLabel - klasa odpowiedzialna za tworzenie i obsługę notyfikacji kontrolki static;
- WndEdit - klasa odpowiedzialna za tworzenie i obsługę notyfikacji kontrolki edit;
- WndButton - klasa odpowiedzialna za tworzenie i obsługę notyfikacji kontrolki button;
- WndScrollBar - klasa odpowiedzialna za tworzenie i obsługę notyfikacji kontrolki scrollbar;
- WndListBox - klasa odpowiedzialna za tworzenie i obsługę notyfikacji kontrolki listbox;
- WndComboBox - klasa odpowiedzialna za tworzenie i obsługę notyfikacji kontrolki combobox;
- WndTooltip - klasa odpowiedzialna za tworzenie i obsługę notyfikacji kontrolki tooltip służącej do wyświetlania podpowiedzi/opisów kontekstowych innych kontrolek.

Cały kod poszczególnych klas wraz z przykładem ich zastosowania zamieściłem na stronie GitHub. Jedynie pokażę jak można tworzyć kontrolki za ich pomocą. Oto jak tworzone są kontrolki w komunikacie WM_CREATE:
- case WM_CREATE:
- {
- NONCLIENTMETRICS ncm;
- ncm.cbSize=sizeof(ncm);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
- font = CreateFontIndirect(&ncm.lfStatusFont);
- myEdit = new WndEdit( // Create WndEdit control object
- "some edit stuff", // text to set in edit control
- ws::window::ws_child // control styles: as child window
- | ws::window::ws_visible // as visible window
- | ws::window::ws_hscrollbar // as window with horizontal scroll bar
- | ws::window::ws_vscrollbar // as window with vertical scroll bar
- | ws::edit::es_autohscroll // as edit control with auto horizontal scroll
- | ws::edit::es_autovscroll // as edit control with auto vertical scroll
- | ws::edit::es_multiline, // as multiline edit control
- 100, // x - position
- 0, // y - position
- 100, // width
- 50, // height
- hWnd, // handle to parent window
- (HMENU) 5000, // in this case id of control
- hInst, // handle to application instance
- NULL // pointer to some extra data stuff (in this cas NULL means no extra data stuff)
- );
- // set myEdit object control font
- myEdit->setFont(font);
- myScrollBar = new WndScrollBar( // create WndScrollBar object of control ScrollBar
- ws::window::ws_child| // Style of control: as child
- ws::window::ws_visible| // as visible
- ws::scrollbar::sbs_horizontal, // as hotizontal scroll bar
- 100, // x - position
- 50, // y - position
- 100, // width
- 20, // height
- hWnd, // parent window handle
- (HMENU) 5001, // in this case it is a id of control
- hInst, // handle to application instance
- NULL // pointer to some extra data stuff (in this cas NULL means no extra data stuff)
- );
- SCROLLINFO si; // structure describe setting of scroll bar control
- si.cbSize = sizeof(SCROLLINFO); // this parameter must be set
- si.fMask = SIF_ALL; // flag describing whitch of struct field will be used
- si.nMax = 110; // maximum value + nPage - 1
- si.nMin = 0; // minimum value
- si.nPage = 11; // page scrolling size
- si.nPos = 0; // current scroll bar pos
- si.nTrackPos = 0; // current track pos
- myScrollBar->setScrollInfo(&si, false); // set settings of scrollbar
- myScrollBar->setThumbtract(true); // this means that when user move control slider then value of nPos Scroll Bar is changed
- // add some notification command for myScrollBar object control
- myScrollBar->addNotification(WndScrollBar::notifications::wmscroll, new OnScrollChanged(myEdit, myScrollBar));
- myListBox = new WndListBox( // create WndListBox window object
- ws::window::ws_hscrollbar| // with styla: hotizontal scrollbar
- ws::window::ws_vscrollbar| // vertical scrollbar
- ws::window::ws_child| // as child window
- ws::window::ws_visible| // as visible widnow
- ws::listbox::lbs_notify| // with sending notification code
- ws::listbox::lbs_hasstrings,// with string data item
- 100, // x-position
- 70, // y-position
- 100, // control width
- 100, // control height
- hWnd, // parent window handle
- (HMENU) 5002, // in this case it is an window ID
- hInst, // application instance handle
- NULL // pointer to some extra data (in this case NULL - means no extra data)
- );
- // add items to list box
- myListBox->addTextItem("Polska");
- myListBox->addTextItem("Czechy");
- myListBox->addTextItem("Słowacja");
- myListBox->addTextItem("Litwa");
- myListBox->addTextItem("Łotwa");
- myListBox->addTextItem("Estonia");
- myListBox->addTextItem("Węgry");
- myListBox->addTextItem("Stany Zjednoczone Ameryki");
- // set myListBox font
- myListBox->setFont(font);
- // add some notifications stuff
- myListBox->addNotification(WndListBox::notifications::selchange, new OnListBoxSelChanged(myEdit, myListBox)); // notification command for selchange notify
- myListBox->addNotification(WndListBox::notifications::doubleclick, new OnListBoxDblClick(myEdit, myListBox)); // notification command for doubleclick notify
- myLabel = new WndLabel( // create WndLabel object of Static control
- "Label", // text to write in window
- ws::window::ws_child| // window style: as child
- ws::window::ws_visible| // as visible
- ws::label::ss_notify, // with sending notifications to parent window
- 100, // x - position
- 170, // y - position
- 100, // width
- 20, // height
- hWnd, // parent window handle
- (HMENU) 5003, // in this case id of cotrol
- hInst, // handle to application instance
- NULL // pointer to some extra data (in this case NULL - means no extra data)
- );
- // set myLabel font
- myLabel->setFont(font);
- // add notification command object to myLabel control
- myLabel->addNotification(WndLabel::notifications::clicked, new OnLabelClick(myLabel));
- myComboBox = new WndComboBox( // create WndComboBox class object of combobox control
- ws::window::ws_child| // with style: as child
- ws::window::ws_visible| // as visible
- ws::window::ws_vscrollbar| // with vertical scrollbar
- ws::combobox::cbs_hasstrings| // with string data for stored items
- ws::combobox::cbs_dropdown, // with drop down list
- 100, // x - position
- 190, // y - position
- 100, // width
- 100, // height (including drop down list height)
- hWnd, // handle to parent window
- (HMENU) 5004, // in this case control id
- hInst, // application instance handle
- NULL // pointer to some extra data (in this case NULL - means no extra data)
- );
- // add items to combo box
- myComboBox->addTextItem("Polska");
- myComboBox->addTextItem("Czechy");
- myComboBox->addTextItem("Słowacja");
- myComboBox->addTextItem("Litwa");
- myComboBox->addTextItem("Łotwa");
- myComboBox->addTextItem("Estonia");
- myComboBox->addTextItem("Węgry");
- myComboBox->addTextItem("Stany Zjednoczone Ameryki");
- myComboBox->setFont(font);
- myComboBox->addNotification(WndComboBox::notifications::selchange, new OnComboBoxSelChanged(myEdit, myComboBox));
- }
- break;
Ważnym elementem obsługi kontrolek w WinApi są notyfikacje, czyli komunikaty pochodzące od danej kontrolki wysyłane do okna rodzica. Mechanizm podpinania jest bardzo prosty i przytoczę tutaj jeden przykładowy wycinek z listing-u 1:
- myComboBox->addNotification(WndComboBox::notifications::selchange, new OnComboBoxSelChanged(myEdit, myComboBox));
To co jest wykonywane w powyższym fragmencie kodu to podpinanie pod zdarzenie (notyfikację) typu selchange obiektu klasy OnComboBoxSelChanged. Klasa ta dziedziczy po specjalnie utworzonym interfejsie INotificationCommand, który dysponuje czysto wirtualną metodą notify. To ta metoda będzie wywoływana, gdy obiekt wyśle notyfikację do okna rodzica. Do obsługi więc notyfikacji konieczne jest utworzenie takiej klasy. Oto przykład:
- class OnComboBoxSelChanged : public INotificationCommand{
- public:
- WndEdit* edit;
- WndComboBox* combobox;
- OnComboBoxSelChanged(WndEdit* edit, WndComboBox* combobox) : edit(edit), combobox(combobox){}
- virtual void notify(){
- edit->setWindowText(combobox->getSelectedText());
- }
- };
Klasa OnComboBoxSelChanged przechowuje dane niezbędne do realizacji zadań wykonywanych w metodzie notify. Niestety samo podpięcie klasy nie wystarczy, trzeba jeszcze obsłużyć komunikat WM_COMMAND, gdzie lądują notyfikacje wysyłane przez okna potomne. Oto przykładowy kod:
- case WM_COMMAND:
- {
- UINT nc = HIWORD(wParam);
- UINT id = LOWORD(wParam);
- HWND ctrl = (HWND) lParam;
- if(myListBox->notify(ctrl, id, nc)) // doing notification stuff for myListBox control object
- break;
- if(myLabel->notify(ctrl, id, nc)) // doing notification stuff for myLabel control object
- break;
- if(myComboBox->notify(ctrl, id, nc)) // doing notification stuff for myComboBox control object
- break;
- }
- break;
Jak widać metoda notify wywołana w komunikacie WM_COMMAND wykonuje całą brudną robotę związaną z obsługą notyfikacji i zwraca wartość niezerową, gdy notyfikacja została obsłużona.

Tytuł:
Architektura oprogramowania bez tajemnic. Wykorzystaj język C++ do tworzenia wydajnych aplikacji i systemów
Autor:
Adrian Ostrowski, Piotr Gaczkowski

Tytuł:
Opus magnum C++ 11. Programowanie w języku C++. Wydanie II poprawione (komplet)
Autor:
Jerzy Grębosz

Tytuł:
Programowanie wieloplatformowe z C++ i wxWidgets 3
Autor:
Bartosz W. Warzocha

Tytuł:
Język C++ i przetwarzanie współbieżne w akcji. Wydanie II
Autor:
Anthony Williams

Tytuł:
C++ dla bystrzaków. Wydanie VII
Autor:
Stephen R. Davis

Tytuł:
Tablice informatyczne. Podstawy C++
Autor:
Radosław Sokół

Tytuł:
Opus magnum C++11. Programowanie w języku C++ (komplet)
Autor:
Jerzy Grębosz

Tytuł:
OpenCV 3. Komputerowe rozpoznawanie obrazu w C++ przy użyciu biblioteki OpenCV
Autor:
Adrian Kaehler, Gary Bradski

Tytuł:
C++ w 24 godziny. Wydanie VI
Autor:
Rogers Cadenhead, Jesse Liberty

Tytuł:
C++ Optymalizacja kodu. Sprawdzone techniki zwiększania wydajności
Autor:
Guntheroth Kurt