• Nie Znaleziono Wyników

Wprowadzenie

N/A
N/A
Protected

Academic year: 2021

Share "Wprowadzenie"

Copied!
49
0
0

Pełen tekst

(1)

Programowanie w środowiskach RAD

Programowanie w środowiskach RAD

Język C++ w środowiskach RAD

Język C++ w środowiskach RAD

Roman Simiński

roman.siminski@us.edu.pl www.siminskionline.pl

Programowanie sterowane zdarzeniami

Geneza, koncepcja, rodzaje, przykłady

(2)

Jeszcze wcale nie tak dawno temu …

Jeszcze wcale nie tak dawno temu …

2 Programowanie w środowiskach RAD |

Komputery wykorzystywały tekstowy tryb pracy

monitora a użytkownicy …

(3)

Jeszcze wcale nie tak dawno temu …

Jeszcze wcale nie tak dawno temu …

3 Programowanie w środowiskach RAD |

(4)

Podstawą programowania były „sekwencja” i „dyktatura”

Podstawą programowania były „sekwencja” i „dyktatura”

4 Programowanie w środowiskach RAD | Program ma ściśle określony początek i koniec.

Sekwencja — wykonanie programu od początki

do końca, pod „dyktando” kolejnych instrukcji napisanych przez programistę.

Dyktatura — program dominuje, realizuje

scenariusz określony kodem, użytkownik wykonuje operacje pod dyktando programu.

Nikła interakcja — informacje wprowadzane

przez użytkownika mają wpływ na wykonanie programu, ale zwykle jest on niewielki.

To jest: int main() { Data data; init(); readData( &data ); processData( &data ) showData( &data ); done(); return 0; } int main() { Data data; init(); readData( &data ); processData( &data ) showData( &data ); done(); return 0; } int main() { char key; do { showMenuItems();

switch( key = getKey() ) { case '1' : doAction1(); break; case '2' : doAction2(); break; } }

while( key != ESC ); return 0; } int main() { char key; do { showMenuItems();

switch( key = getKey() ) { case '1' : doAction1(); break; case '2' : doAction2(); break; } }

while( key != ESC ); return 0; } Przetwarzanie wsadowe Przetwarzanie wsadowe Prosta interakcja Prosta interakcja

Programowanie kierowane przepływem sterowania

flow driven programming

Programowanie kierowane przepływem sterowania flow driven programming

(5)

Programowanie kierowane przepływem sterowania

Programowanie kierowane przepływem sterowania

5 Programowanie w środowiskach RAD | Flow driven programming

Jest to tradycyjna technika programowania, w ramach której program

wykonywany jest zgodnie z aktualną ścieżką przepływu sterowania, zmienianą przez instrukcje warunkowe i iteracyjne, w oparciu o dane zewnętrzne

i wewnętrzne, dostarczane do programu oraz wartościowane w zdeterminowanych momentach jego wykonania.

Ta technika programowania stosowana jest powszechnie w jednozadaniowych systemach, ukierunkowanych na przetwarzanie sterowanie prostymi

poleceniami klawiaturowymi, zwykle w środowiskach znakowych.

Aktualnie stanowi postawę realizacji systemów preferujących przetwarzanie wsadowe, wykorzystujących uproszczoną interakcję z użytkownikiem.

(6)

A co z programami wykorzystującymi tryb graficzny?

A co z programami wykorzystującymi tryb graficzny?

6 Programowanie w środowiskach RAD | Tryb graficzny wykorzystywany był tylko w wyspecjalizowanych aplikacjach:

programach graficznych — tworzenie i obróbka,

systemach CAD/CAM (Pierre Bézier i Paula de Casteljau), grach komputerowych,

programach specjalizowanych — np. poligrafia. Problemy:

Problemy z pracą w trybie graficznym (karty, tryby, sterowniki). Zbyt słaby sprzęt, brak wsparcia ze strony systemu operacyjnego. Brak standaryzacji w zakresie graficznego interfejsu użytkownika. Utrudniona nawigacja — raczkujące urządzenia wskazujące.

(7)

W końcu jednak komputery „zmężniały”

W końcu jednak komputery „zmężniały”

7 Programowanie w środowiskach RAD |

Powstają systemy operacyjne wykorzystujące:

GUI – graphical user interface

czyli

graficzny podsystem komunikacji

z użytkownikiem

zwany też:

(8)

Prawdziwy zamęt wprowadziły jednak „gryzonie”...

Prawdziwy zamęt wprowadziły jednak „gryzonie”...

8 Programowanie w środowiskach RAD |

Czy GUI wpływa na sposób programowania

aplikacji?

Tak – aplikacje z GUI programuje się trudniej

Ale prawdziwe zamieszania wprowadza pojawienie

się w powszechnym użytku:

(9)

Od Dyktatora do Sługi — upadek programisty... ?

Od Dyktatora do Sługi — upadek programisty... ?

9 Programowanie w środowiskach RAD |

Świat programisty

Świat

programisty użytkownikaŚwiat

Świat użytkownika

Kliknę sobie

tam, gdzie chcę i kiedy chcę! Ten komputer jest

mój...! Kiedyś to ja

dyktowałem warunki, a teraz muszę kombinować, co

(10)

Zmierzch programowania sterowanego przypływem — FCP

Zmierzch programowania sterowanego przypływem — FCP

10 Programowanie w środowiskach RAD | Rozwój GUI i manipulatorów myszopodobnych zmienił techniki programowania. Na zmiany wpłynął również rozwój architektury klient-serwer oraz protokołów wykorzystujących tę koncepcję (czyli większość protokołów internetowych).

Ja tu rządzę i dyktuję warunki! Czekam i wykonuję polecenia 1970 1980 1990 2000 2010 FCP FDP FDP

(11)

Klient-serwer, sieć, przetwarzanie rozproszone

Klient-serwer, sieć, przetwarzanie rozproszone

11 Programowanie w środowiskach RAD |

Klient Żądanie Odpowiedź Serwer Nasłuchiwanie Działanie na żądanie Żądanie usługi Klient

(12)

Programowanie sterowane zdarzeniami

Programowanie sterowane zdarzeniami

12 Programowanie w środowiskach RAD | Event driven programming — EDP

Nowa (relatywnie) technika programowania, zakładająca że działanie

programu polega na wykonywaniu akcji będących odpowiedzią na zdarzenia dotyczące programu.

Zdarzenia mogą pochodzić z otoczenia programu (użytkownik, system, sieć) lub z jego wnętrza.

Zdarzenia powstają zwykle asynchronicznie w stosunku do działania

programu, ten nie kontroluje momentu powstania zdarzeń oraz ich źródła (za wyjątkiem zdarzeń wewnętrznych).

(13)

Zasada Hollywood — Hollywood Principle

Zasada Hollywood — Hollywood Principle

13 Programowanie w środowiskach RAD |

http://c2.com/cgi/wiki?HollywoodPrinciple

(14)

Event driven programming — koncepcja organizacji

Event driven programming — koncepcja organizacji

14 Programowanie w środowiskach RAD |

http://eventdrivenpgm.sourceforge.net/ Dyspozytor Dispatcher Dyspozytor Dispatcher Obsługiwacz — Handler Obsługiwacz — Handler Obsługiwacz — Handler Obsługiwacz — Handler Obsługiwacz — Handler Obsługiwacz — Handler Zdarzenie Event Zdarzenie Event Zdarzenie Event Zdarzenie Event Zdarzenie Event Zdarzenie Event ● ● ● ● ● ●

(15)

Koncepcja stara jak świat i powszechnie znana

Koncepcja stara jak świat i powszechnie znana

15 Programowanie w środowiskach RAD |

● ● ● ● ● ●

Zlecenia klientów Obsługa zlecenia

Przyjmowanie zleceń Kierowanie do obsługi

(16)

Zdarzenia — events

Zdarzenia — events

16 Programowanie w środowiskach RAD | Zdarzenie (ang. event) – wynik asynchronicznej w stosunku do działania

programu akcji użytkownika, urządzenia lub programu. Zdarzenie jest

rejestrowane, oraz zapamiętywany jest jego kontekst.

Zdarzenie w sensie programistycznym, to informacja pewnym zdarzeniu

rzeczywistym, które jest istotne dla systemu informatycznego i powinno zostać

w pewien sposób obsłużone.

Zdarzenia generowane są zwykle przez otoczenie systemu — użytkowników, inne systemy, urządzenia sprzętowe (sensory, czujniki), system operacyjny i jego

składowe.

Zdarzenia generowane są również przez sam system — różne składowe systemu mogą generować być źródłem zdarzeń kierowanych do innych składowych tego samego systemu jak i do jego otoczenia.

(17)

Zdarzenia — events

Zdarzenia — events

17 Programowanie w środowiskach RAD | !

Zdarzenie jako element rzeczywistości Zdarzenie jako informacja dla systemu

(18)

Źródła zdarzeń

Źródła zdarzeń

18 Programowanie w środowiskach RAD | Zdarzenie

Event

Zdarzenie Event

(19)

Przykład rekordu opisu informacji o zdarzeniu

Przykład rekordu opisu informacji o zdarzeniu

19 Programowanie w środowiskach RAD |

struct EventInfo {

int what; // Rodzaj zdarzenia int code; // Kod zdarzenia

int key; // Informacja o zdarzeniu klawiaturowym int x, y; // Informacja o pozycji kursora myszy int buttons; // Informacja o stanie przycisków myszy };

struct EventInfo {

int what; // Rodzaj zdarzenia int code; // Kod zdarzenia

int key; // Informacja o zdarzeniu klawiaturowym int x, y; // Informacja o pozycji kursora myszy int buttons; // Informacja o stanie przycisków myszy };

Przykład opisu informacji o zdarzeniu — rekord zawierający pola to typie zdarzenia, umownym kodzie w ramach danego typu, informacje o klawiaturze i myszy:

W rzeczywistości rekordy opisu zdarzenia są zwykle bardziej skomplikowana i zwierają więcej informacji. Powyższy przykład ma charakter poglądowy.

(20)

Procedury obsługi zdarzeń — event handlers

Procedury obsługi zdarzeń — event handlers

20 Programowanie w środowiskach RAD | Procedura obsługi zdarzenia (ang. event handler) – wydzielony fragment

oprogramowania obsługujący zdarzenie lub zdarzenia odpowiedniego rodzaju. W obrębie aplikacji to najczęściej podprogram otrzymujący informację

o zaistniałym zdarzeniu, obsługujący to zdarzenie zgodnie z logiką aplikacji. Procedury obsługi są zazwyczaj dedykowane dla konkretnych typów zdarzeń. Po pomyślnej obsłudze zdarzenia informacje o nim są zerowane lub w opisie zdarzenia umieszcza się informację o jego obsłużeniu.

(21)

Procedury obsługi zdarzeń — event handlers

Procedury obsługi zdarzeń — event handlers

21 Programowanie w środowiskach RAD |

void handleMouseDown( EventInfo event ) {

Control control = findControlOnXY( event.x, event.y ); if( control == NULL )

return;

switch( control.type ) {

case NORMAL_BUTTON : pressButton( control ); event.what = EV_NONE; break;

case RADIO_BUTTON : markRadioButton( control ); event.what = EV_NONE;

break;

case CHECK_BUTTON : markCheckBox( control ); event.what = EV_NONE; break;

} }

void handleMouseDown( EventInfo event ) {

Control control = findControlOnXY( event.x, event.y ); if( control == NULL )

return;

switch( control.type ) {

case NORMAL_BUTTON : pressButton( control ); event.what = EV_NONE; break;

case RADIO_BUTTON : markRadioButton( control ); event.what = EV_NONE;

break;

case CHECK_BUTTON : markCheckBox( control ); event.what = EV_NONE; break;

} }

Przykładowa, hipotetyczna procedura obsługi zdarzenia pochodzącego z myszki (zakładamy, że Control to typ elementów okna dialogowego):

(22)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

22 Programowanie w środowiskach RAD | Dyspozytor (ang. dispatcher) – zadaniem dyspozytora jest pobieranie

napływających zdarzeń, identyfikowanie ich i kierowanie do odpowiednich procedur obsługi (żargonowo: handlerów).

Dyspozytor pracuje zazwyczaj iteracyjnie — wyjście z iteracji następuje po zidentyfikowaniu zdarzenia końca.

Dyspozytor powinien radzić sobie w sytuacji, gdy zdarzenie nie zostało obsłużone w żadnej z procedur obsługi.

Dyspozytor może dokonywać konwersji zdarzeń — dostosowując je do specyfiki działania aplikacji.

(23)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

23 Programowanie w środowiskach RAD |

int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; } int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; }

Pseudokod głównej iteracji programu — pierwsza faza pracy dyspozytora, podejście proceduralne.

Definicja rekordu opisu zdarzenia Definicja rekordu opisu zdarzenia

Uwaga — to tylko przykład jednego z możliwych sposobów organizacji pracy dyspozytora.

(24)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

24 Programowanie w środowiskach RAD |

int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; } int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; }

Pseudokod głównej iteracji programu — pierwsza faza pracy dyspozytora, podejście proceduralne.

Pętla, czyli iteracja bez określonego warunku zakończenia (czasem instr. loop)

Pętla, czyli iteracja bez określonego warunku zakończenia (czasem instr. loop)

Uwaga — to tylko przykład jednego z możliwych sposobów organizacji pracy dyspozytora.

(25)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

25 Programowanie w środowiskach RAD |

int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; } int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; }

Pseudokod głównej iteracji programu — pierwsza faza pracy dyspozytora, podejście proceduralne.

Sprawdzenie, czy dostępne jest

następne zdarzenie. Jeżeli tak, to jest pobierane, jeżeli nie to koniec działania.

Sprawdzenie, czy dostępne jest

następne zdarzenie. Jeżeli tak, to jest pobierane, jeżeli nie to koniec działania.

Uwaga — to tylko przykład jednego z możliwych sposobów organizacji pracy dyspozytora.

(26)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

26 Programowanie w środowiskach RAD |

int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; } int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; }

Pseudokod głównej iteracji programu — pierwsza faza pracy dyspozytora, podejście proceduralne.

Czy wykryte zdarzenie nie jest czasem sygnałem zakończenia programu?

Czy wykryte zdarzenie nie jest czasem sygnałem zakończenia programu?

Uwaga — to tylko przykład jednego z możliwych sposobów organizacji pracy dyspozytora.

(27)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

27 Programowanie w środowiskach RAD |

int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; } int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; }

Pseudokod głównej iteracji programu — pierwsza faza pracy dyspozytora, podejście proceduralne.

Wstępne przetworzenie informacji o zdarzeniu, konwersja, zamiana, czasem sztuczki i triki Wstępne przetworzenie informacji o zdarzeniu,

konwersja, zamiana, czasem sztuczki i triki

Uwaga — to tylko przykład jednego z możliwych sposobów organizacji pracy dyspozytora.

(28)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

28 Programowanie w środowiskach RAD |

int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; } int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; }

Pseudokod głównej iteracji programu — pierwsza faza pracy dyspozytora, podejście proceduralne.

Czy jest rzeczywiście coś do zrobienia? Czy jest rzeczywiście coś do zrobienia?

Uwaga — to tylko przykład jednego z możliwych sposobów organizacji pracy dyspozytora.

(29)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

29 Programowanie w środowiskach RAD |

int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; } int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; }

Pseudokod głównej iteracji programu — pierwsza faza pracy dyspozytora, podejście proceduralne.

Przekazanie zdarzeń do konkretnych procedur obsługi

Przekazanie zdarzeń do konkretnych procedur obsługi

Uwaga — to tylko przykład jednego z możliwych sposobów organizacji pracy dyspozytora.

(30)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

30 Programowanie w środowiskach RAD |

int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; } int main() { EventInfo event; for( ; ; ) { event = getNextEvent();

if( event.what == EV_QUIT ) break;

preprocessEvent( event ); if( event.what != EV_NONE ) forwardEvent( event ); else idleAction(); } return EXIT_SUCCESS; }

Pseudokod głównej iteracji programu — pierwsza faza pracy dyspozytora, podejście proceduralne.

Gdy nie wykryto oczekującego na obsługę zdarzenia — obsługa procesu realizowanego w tle

Gdy nie wykryto oczekującego na obsługę zdarzenia — obsługa procesu realizowanego w tle

Uwaga — to tylko przykład jednego z możliwych sposobów organizacji pracy dyspozytora.

(31)

Dyspozytor — dispatcher

Dyspozytor — dispatcher

31 Programowanie w środowiskach RAD |

void forwardEvent( EventInfo event ) {

switch( event.what ) {

case EV_MOUSE_DOWN : handleMouseDown( event ); break;

case EV_KEY_DOWN : handleKeyPress( event ); break;

case EV_APP_EVENT : handleApplEvent( event ); break;

default : handleUnknown( event ); break;

}

if( event.what != EV_NONE )

processUnhandledEvent( event ); }

void forwardEvent( EventInfo event ) {

switch( event.what ) {

case EV_MOUSE_DOWN : handleMouseDown( event ); break;

case EV_KEY_DOWN : handleKeyPress( event ); break;

case EV_APP_EVENT : handleApplEvent( event ); break;

default : handleUnknown( event ); break;

}

if( event.what != EV_NONE )

processUnhandledEvent( event ); }

Szczegółowa identyfikacja zdarzenia i przekazanie do procedur obsługi zgodnie z typem zdarzenia.

(32)

A gdy zdarzenia pojawiają się zbyt szybko...

A gdy zdarzenia pojawiają się zbyt szybko...

32 Programowanie w środowiskach RAD |

Handler Handler Handler Handler Handler Handler Event Event Event Event Event Event ● ● ● ● ● ● Dispatcher Dispatcher

Kolejka (ang. queue) Kolejka (ang. queue)

Kolejka zdarzeń(ang. event queue) – struktura danych typu FIFO, przechowująca informacje o zdarzeniach. Kolejka może być priorytetowa, istnieje możliwość reorganizowania kolejności kolejkowanych zdarzeń.

(33)

Model EDP bardziej szczegółowo...

Model EDP bardziej szczegółowo...

33 Programowanie w środowiskach RAD |

Handler Handler Handler Handler Handler Handler Event Event ● ● ● ● ● ● Dispatcher Dispatcher Main Event Loop Main Event Loop Events Forwarding Events Forwarding Event Event Event Event

(34)

Model EDP jeszcze bardziej szczegółowo, cd. ...

Model EDP jeszcze bardziej szczegółowo, cd. ...

34 Programowanie w środowiskach RAD |

Handler Handler Handler Handler Event Event ● ● ● ● ● ● Dispather Dispather Main Event Loop Main Event Loop Events Forwarding Events Forwarding Event Event Event Event Events sources Events sources Handler Handler

(35)

Environment & Network Local machine

OS

Application

EDP, ale gdzie?

EDP, ale gdzie?

35 Programowanie w środowiskach RAD |

Handler Handler Handler Handler Event Event ● ● ● ● ● ● Dispather Dispather Main Event Loop Main Event Loop Events Forwarding Events Forwarding Event Event Event Event Events sources Events sources Handler Handler

(36)

Environment & Network Local machine

OS

Application

EDP, ale gdzie?

EDP, ale gdzie?

36 Programowanie w środowiskach RAD |

Handler Handler Handler Handler Event Event ● ● ● ● ● ● Dispather Dispather Main Event Loop Main Event Loop Events Forwarding Events Forwarding Event Event Event Event Events sources Events sources Handler Handler

(37)

Environment & Network Host OS Application Local machine OS Application

EDP, ale gdzie?

EDP, ale gdzie?

37 Programowanie w środowiskach RAD |

Handler Handler Handler Handler Event Event ● ● ● ● ● ● Dispather Dispather Main Event Loop Main Event Loop Events Forwarding Events Forwarding Event Event Event Event Events sources Events sources Handler Handler

(38)

Environment & Network Host OS Request broker Host OS Services

EDP, ale gdzie?

EDP, ale gdzie?

38 Programowanie w środowiskach RAD |

Handler Handler Handler Handler Event Event ● ● ● ● ● ● Dispather Dispather Main Event Loop Main Event Loop Events Forwarding Events Forwarding Event Event Event Event Events sources Events sources Handler Handler

(39)

Event driven programming a OOP i GUI

Event driven programming a OOP i GUI

39 Programowanie w środowiskach RAD | Koncepcja programowania sterowanego zdarzeniami jest niezależna od przyjętej metody programowania i stosowanego języka.

Podejście obiektowe jest jednak metodą programowania idealnie pasująca do koncepcji programowania sterowanego zdarzeniami.

Programowanie sterowane zdarzeniami kojarzy się głównie z systemami

wykorzystującymi GUI — jednak ta koncepcja programowania może być skutecznie wykorzystywana w systemach bez GUI (np. procesor i mechanizm przerwań jest

event driven!).

Wiele zagadnień jest podatnych na rozwiązanie event driven — np. parsery, w tym parsery XML.

Większość bibliotek obsługi GUI zintegrowanych abo bliskich systemowi operacyjnemu (WinAPI, XWindows, GTK) zaimplementowano w językach

nieobiektowych (zwykle C), choć w sensie koncepcji są one przynajmniej obiektowo

(40)

Event driven programming a OOP i GUI, cd. ...

Event driven programming a OOP i GUI, cd. ...

40 Programowanie w środowiskach RAD | Programowanie na poziomie bibliotek GUI bliskich systemowi operacyjnemu jest żmudne. A co żmudne, jest trudne, a przynajmniej uciążliwe.

Twórcy narzędzi dla programistów od lat pracują nad bibliotekami GUI umożliwiającymi łatwiejsze i efektywniejsze programowanie.

Te biblioteki ze większości przypadków są obiektowe.

Historycznie najwcześniejszymi bibliotekami były MFC (Microsoft) i OWL

(Borland). Borland firmował również świetną! bibliotekę TurboVision dla DOS. Wraz z pojawieniem się pakietu Delphi firma Borland udostępnia bibliotekę VCL, dostępną aktualnie we wszystkich narzędziach wywodzących się z firmy Borland. W świecie społeczności OpenSource powstają biblioteki wxWidgets oraz Qt, ta ostatnia staje się podstawą programu QTDesigner oraz pakietu QTCreator, aktualnie firmowanego przez Nokię.

(41)

Event driven programming a WinAPI

Event driven programming a WinAPI

41 Programowanie w środowiskach RAD |

Działające programy Działające programy System operacyjny System operacyjny Identyfikowanie zdarzeń Identyfikowanie zdarzeń Identyfikowanie odbiorcy Identyfikowanie odbiorcy MSG MSG Usługi i programy systemowe Usługi i programy systemowe MSG MSG MSG MSG Podwójne kliknięcie na pozycji X: 100 Y: 150 Podwójne kliknięcie na pozycji X: 100 Y: 150 X: 100 Y: 150X: 100 Y: 150

(42)

Event driven programming a WinAPI

Event driven programming a WinAPI

42 Programowanie w środowiskach RAD |

typedef struct { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG; typedef struct { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG;

hwnd — identyfikator okna, które otrzymuje komunikat.

message — identyfikator komunikatu, starszy bajt zarezerwowany dla systemu,

młodszy do wykorzystania dla programów.

wParam, lParam — dodatkowe informacje o komunikacie, zależne od jego

rodzaju.

time — Czas „zaistnienia” komunikatu.

(43)

Event driven programming a WinAPI

Event driven programming a WinAPI

43 Programowanie w środowiskach RAD |

typedef struct { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG; typedef struct { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG;

Identyfikator komunikatu message zawiera najczęściej nazwaną stałą określającą zaistniałe zdarzenie.

Procedura obsługi zdarzenia sprawdza pole message i podejmuje stosowną obsługę, być może posiłkując się dodatkowymi polami rekordu MSG.

Przykład — identyfikator WM_PAINT oznacza, że zaistniało zdarzenie powodujące konieczność przerysowania zawartości obszaru klienckiego okna, co powinna

zrealizować procedura obsługi komunikatów.

To pole ma znaczenie podstawowe i określa charakter komunikatu

To pole ma znaczenie podstawowe i określa charakter komunikatu

(44)

Event driven programming a WinAPI

Event driven programming a WinAPI

44 Programowanie w środowiskach RAD | Komunikaty opisujące zdarzenia są kolejkowane.

System obsługuje pojedynczą systemową kolejkę

komunikatów oraz kolejki przydzielane indywidualnie dla każdego programu (wątku) wykorzystującego GUI.

Działające programy Działające programy System operacyjny System operacyjny Identyfikowanie zdarzeń Identyfikowanie zdarzeń Identyfikowanie odbiorcy Identyfikowanie odbiorcy Usługi i programy systemowe Usługi i programy systemowe MSG MSG MSG MSG Program A Program A Program B Program B

Komunikaty wstawiane są do systemowej kolejki, skąd są pobierane przez system.

Po określeniu odbiorcy, komunikat wstawiany jest do indywidualnej kolejki programu (wątku).

(45)

Dyspozytor w WinAPI

Dyspozytor w WinAPI

45 Programowanie w środowiskach RAD |

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmdLine, int nCmdShow ) {

WNDCLASSEX winClass; HWND hWndMain;

MSG msg; . . .

ShowWindow( hWndMain, nCmdShow); UpdateWindow( hWndMain );

while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return msg.wParam; }

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmdLine, int nCmdShow ) {

WNDCLASSEX winClass; HWND hWndMain;

MSG msg; . . .

ShowWindow( hWndMain, nCmdShow); UpdateWindow( hWndMain );

while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return msg.wParam; }

Pobranie komunikatu z kolejki Pobranie komunikatu z kolejki

Przekształcenie komunikatów związanych z klawiaturą.

Przekształcenie komunikatów związanych z klawiaturą.

Odnalezienie i uruchomienie przez system operacyjny

procedury obsługi komunikatu

Odnalezienie i uruchomienie przez system operacyjny

(46)

Schemat obiegu komunikatów na poziomie WinAPI

Schemat obiegu komunikatów na poziomie WinAPI

46 Programowanie w środowiskach RAD |

System operacyjny System operacyjny Program Program GetMessage GetMessage TranslateMessage TranslateMessage DispatchMessage DispatchMessage msg msg Procedura obsługi komunikatów Procedura obsługi komunikatów Inne podprogramy Inne podprogramy Usługi i programy systemowe Usługi i programy systemowe 1 1 1

1 Pobranie komunikatu z kolejki programu

2 2 2

2 Wstawienie informacji do rekordu komunikatu

3 3 44 3 3 44 Translacja komu-nikatów 5 5 5 5 Pobranie komunikatu do obsługi 6 6 Przekazanie komuni-katu do procedury obsługi 6 6 Zarejestrowana klasa okna programu Zarejestrowana klasa okna programu lpfnWndProc lpfnWndProc

(47)

Procedura okna — procedura obsługi komunikatów

Procedura okna — procedura obsługi komunikatów

47 Programowanie w środowiskach RAD |

LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )

{

switch( uMsg ) {

case WM_CLOSE: DestroyWindow( hWnd ); break;

case WM_DESTROY: PostQuitMessage( 0 ); break;

default: return DefWindowProc( hWnd, uMsg, wParam, lParam ); }

return 0; }

LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )

{

switch( uMsg ) {

case WM_CLOSE: DestroyWindow( hWnd ); break;

case WM_DESTROY: PostQuitMessage( 0 ); break;

default: return DefWindowProc( hWnd, uMsg, wParam, lParam ); }

return 0; }

Komunikat oznaczający zdarzenie zamknięcia okna. Usuń okno główne i potomne, wstaw

komunikat WM_DESTROY

Komunikat oznaczający zdarzenie zamknięcia okna. Usuń okno główne i potomne, wstaw

komunikat WM_DESTROY

Program się kończy, wstaw komunikat WM_QUIT, który zakończy działanie iteracji sterowanej funkcją GetMessage

Program się kończy, wstaw komunikat WM_QUIT, który zakończy działanie iteracji sterowanej funkcją GetMessage

(48)

Event driven programing... ale w czym?

Event driven programing... ale w czym?

48 Programowanie w środowiskach RAD | Programowanie na poziomie bibliotek bliskich systemowi operacyjnemu jest żmudne — to już było.

Jest idealne dla pisania sprytnych programów blisko zintegrowanych z systemem operacyjnym, lub oprogramowania o wysokich wymaganiach wydajnościowych. Uważam że programowanie na tym poziomie ogranicza programistę tak samo, jak kiedyś ograniczało programowanie złożonych aplikacji w językach symbolicznych. Tematem dalszych wykładów będzie prezentacja koncepcji, technik i wybranych przykładów programowania z wykorzystaniem pakietów C++ Builder i biblioteki

VCL oraz QtCreator i biblioteki Qt.

(49)

Dziękuję za uwagę

Dziękuję za uwagę

Pytania? Polemiki?

Teraz, albo:

Cytaty

Powiązane dokumenty

Uruchom aplikację (Kliknij prawym klawiszem myszy w oknie Project na nazwę projektu, w ukazanym oknie uruchom kolejno Build Project, Deploy Project,

Uruchom aplikację (Kliknij prawym klawiszem myszy w oknie Project na nazwę projektu, w ukazanym oknie uruchom kolejno Build Project, Deploy Project, Run Project lub tylko Run

The pressure caused by the meniscus of the fluid hanging outside the capillary at the same place is P out = 2 ␴ /R, where R is the meniscus radius of curvature, which was

8 Szczegółowy wykaz zaprezentowanych pocztówek z widokiem przedwojennego kościoła Er- löserkirche jak i powojennego kościoła pw. Najświętszego Zbawiciela ze zbiorów dr G.

Księgozbiór Biblioteki Koła SZSiGW liczył 159 publikacji, z czego 155 po- zycji inwentarzowych stanowiły druki zwarte, a 4 – czasopisma i wydawnictwa ciągłe.. Zestawienie

Section 2 considers the problem statement, Section 3 is concerned with the synthesis of the computation model, and Sections 4 and 5 discuss some relevant results from the theory

Hazard assessment involves collection and analyzing data and information from local information to get an idea of the hazard and to determine decisive elements in the hazard

Nie można wykluczyć, że najstarszy z polskich pojemników, okaz z Rrzyżownik, łączyć się może z kręgiem wielkomorawskich oddziaływań na Wielkopolskę, w