C++ pod Windows: 2. časť: Úvod do programovania pod Windows

cplusplus.jpg Me­siac up­ly­nul a ja vás opäť ví­tam pri dru­hej čas­ti se­riá­lu C++ pod Win­dows. V pre­doš­lej čas­ti sme si spo­me­nu­li zá­klad­né po­jmy z prog­ra­mo­va­nia pod Win­dows a uvied­li sme si roz­die­ly med­zi prog­ra­ma­mi pod DOS a Win­dows. Te­raz va­še ve­do­mos­ti roz­ší­ri­me a uve­die­me a ro­zo­be­rie­me si aj ne­ja­ký prog­ram pod Win­dows.

RA­DY, UZ­LY A RU­TI­NY SPRÁV
Už vie­te, že keď ope­rač­ný sys­tém zis­tí po­uží­va­te­ľom spô­so­be­nú uda­losť, vy­ge­ne­ru­je na ňu sprá­vu. Tú­to sprá­vu po­tom po­šle do ra­du správ, kto­rá pris­lúc­ha spus­te­nej ap­li­ká­cii. Ra­dy správ vy­uží­va ap­li­ká­cia, keď chce zis­tiť, či bo­la po­uží­va­te­ľom vy­ge­ne­ro­va­ná sprá­va a o aký druh sprá­vy ide. Zis­tí to tak, že preh­ľa­dá všet­ky sprá­vy v ra­de správ.

Uzol správ je cyk­lus, kto­rý neus­tá­le preh­ľa­dá­va rad správ a zis­ťu­je, či ne­doš­lo k ne­ja­kej uda­los­ti. Pr­vá inštruk­cia toh­to uz­la je vo­la­nie API fun­kcie s náz­vom Get­Mes­sa­ge. Tá­to fun­kcia vra­cia in­for­má­cie o kaž­dej sprá­ve, kto­rá ča­ká v ra­de správ. Po za­vo­la­ní tej­to fun­kcie oby­čaj­ne uzol správ vo­lá nie­koľ­ko ďal­ších fun­kcií, kto­ré ob­slu­hu­jú pr­vky, ako sú vstu­py a vý­stu­py z klá­ves­ni­ce. Na­ko­niec vo­lá uzol správ ďal­šiu API fun­kciu, a to fun­kciu Dis­pat­chMes­sa­ge. Tá­to fun­kcia vo­lá vám už zná­mu fun­kciu ok­na WndProc. WndProc ozná­mi, aký druh uda­los­ti nas­tal, a od­po­vie na ňu vo­la­ním ďal­ších fun­kcií, kto­ré za­is­ťu­je váš prog­ram. Tie­to fun­kcie sa vo­la­jú ru­ti­ny správ.

Ru­ti­ny správ ur­ču­jú, akým spô­so­bom bu­de sprá­va spra­co­va­ná. Ap­li­ká­cie Win­dows sú vy­ba­ve­né rôz­ny­mi druh­mi správ, kto­ré sú ur­če­né na spra­co­va­nie jed­not­li­vých dru­hov správ. Nap­rík­lad ak chce­te, aby po­kle­pa­nie my­šou na ok­no spus­ti­lo zvu­ko­vý sig­nál, mu­sí­te na to vy­tvo­riť inú ru­ti­nu sprá­vy, ako keď chce­te, aby to­to po­kle­pa­nie spô­so­bi­lo vy­pí­sa­nie ne­ja­ké­ho textu. Na obr. 1 mô­že­te vi­dieť dve ru­ti­ny správ. Jed­na má ná­zov WM_PAINT a dru­há WM_DES­TROY. Ich fun­kciu si vy­svet­lí­me na­bu­dú­ce.

cplus.jpg Obr. 1 K vy­svet­le­niu spo­lup­rá­ce ra­du a uz­la správ

PRÍKLAD. Po dl­hom teo­re­tic­kom úvo­de je na­ča­se, aby sme si uvied­li prík­lad, na kto­rom si ob­jas­ní­me pre­be­ra­né po­jmy. Prík­la­dom je jed­no­duc­há ap­li­ká­cia Hello, kto­rej je­di­nou úlo­hou je vy­pí­sa­nie textu Hello, world! do ok­na s náz­vom Prog­ram Hello.

// Hello.c
#in­clu­de <win­dows.h>

long FAR PAS­CAL _export WndProc(HWND hwnd, 
UINT mes­sa­ge, UINT wPa­ram, LONG lPa­ram) 
{
 HDC   hdc;
 HPEN  hpen, hpe­nOld;
 PAINTSTRUCT ps; 
 RECT  rect;   
 switch (mes­sa­ge) {
  ca­se WM_PAINT:
   hdc = Be­gin­Paint(hwnd, &ps);
   Get­Clien­tRect(hwnd, &rect);
   hpen = Crea­te­Pen(PS_SO­LID, 6, RGB(0, 0, 255));
   hpe­nOld = Se­lec­tOb­ject(hdc, hpen);     
   DrawText(hdc, "Hello, world!", -1, &rect,  DT_SIN­GLE­LI­NE | DT_LEFT | DT_TOP);      
   Se­lec­tOb­ject(hdc, hpe­nOld);
   De­le­teOb­ject(hpen);
   En­dPaint(hwnd, &ps);
   re­turn 0;
  ca­se WM_DES­TROY:
   Po­stQuit­Mes­sa­ge(0);
   re­turn 0;
 }
 re­turn DefWin­dowProc(hwnd, mes­sa­ge, wPa­ram, lPa­ram);
}

int PAS­CAL Win­Main(HAND­LE hIn­stan­ce, 
  HAND­LE hPre­vIn­stan­ce, LPSTR lpszCmdPa­ram, int nCmdShow)
{
 sta­tic char szMe­no [] = "Hello";
 HWND  hwnd;
 MSG     msg;
 WNDCLASS wndclass;

 if (!hPre­vIn­stan­ce) {
  wndclass.sty­le   = CS_HRED­RAW | CS_VRED­RAW;	    // typ ok­na
  wndclass.lpfnWndProc   = WndProc;  // me­no fun­kcie, kto­rá je spo­je­ná  s trie­dou ok­na
  wndclass.cbCl­sExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hIn­stan­ce  = hIn­stan­ce;
  wndclass.hI­con   = Loa­dI­con(NULL, IDI_AP­PLI­CA­TION); // na­tiah­nu­tie iko­ny ap­li­ká­cie (ak ste... 
    // ne­de­fi­no­va­li vlas­tnú, na­tiah­ne sa de­fault
  wndclass.hCur­sor    = Load­Cur­sor(NULL, IDC_ARROW);   // na­tiah­nu­tie kur­zo­ra (ak ste... 
    // ne­de­fi­no­va­li vlast­ný, na­tiah­ne sa de­fault
  wndclass.hbr­Background = Get­Stoc­kOb­ject(WHI­TE_BRUSH);  // po­za­die ok­na
  wndclass.lpszMe­nu­Na­me  = NULL;    // in­for­má­cie o me­nu, ak ste ne­ja­ké vy­tvo­ri­li
  wndclass.lpszClas­sNa­me = szMe­no;  // me­no, pod akým sa trie­da ok­na za­re­gis­tru­je
  Re­gis­terClass(&wndclass);
 }
 hwnd = Crea­teWin­dow(szMe­no,  	 // me­no trie­dy ok­na
  "Prog­ram Hello",     		 // ná­zov ok­na
  WS_OVERLAP­PEDWIN­DOW,  	// št­ýl ok­na        
  CW_USE­DE­FAULT,    	     // po­zí­cia ok­na na osi x
  CW_USE­DE­FAULT,    	     // po­zí­cia ok­na na osi y
  CW_USE­DE­FAULT,       // za­čia­toč­ná veľ­kosť na osi x
  CW_USE­DE­FAULT,    	    // za­čia­toč­ná veľ­kosť na osi y
  NULL,      	  	    // hand­le na ro­di­ča ( v na­šom prí­pa­de žiad­ne nie je, pre­to NULL)
  NULL,        	        // hand­le na me­nu ok­na ( v na­šom prí­pa­de žiad­ne nie je, pre­to NULL)
  hIn­stan­ce,     	   	     // hand­le na in­štan­ciu prog­ra­mu
  NULL);       
   ShowWin­dow(hwnd, nCmdShow);
   Up­da­teWin­dow(hwnd);
   whi­le (Get­Mes­sa­ge(&msg, NULL, 0, 0)) {
    Tran­sla­te­Mes­sa­ge(&msg);
    Dis­pat­chMes­sa­ge(&msg); }
   re­turn msg.wPa­ram;
}

VY­SVET­LE­NIE PROG­RA­MU HELLO
Aby ste do­ko­na­le po­cho­pi­li, ako prog­ram Hello pra­cu­je, mu­sí­me si spo­me­núť eš­te nie­čo o hand­le. Hand­le je uka­zo­va­teľ na uka­zo­va­teľ a uka­zu­je na ad­re­su ulo­že­nú v ta­buľ­ke. Hand­le sa vy­uží­va na prís­tup k ob­jek­tom sys­té­mu Win­dows (po­zor, nie k ta­kým ob­jek­tom, aké po­zná­me z C++). Ve­ľa API fun­kcií vra­cia hand­le a ďal­šie po­uží­va­jú hand­le ako pa­ra­me­ter. Keď sa po­zrie­me na fun­kciu Win­Main, tá ob­sa­hu­je hneď dva hand­le, a to hIn­stan­ce, čo je hand­le spus­te­nej ap­li­ká­cie, a hPre­vIn­stan­ce, čo je hand­le pred­chád­za­jú­cej ap­li­ká­cie. Ďal­ším pa­ra­met­rom fun­kcie Win­Main je lpszCmdPa­ram, čo je uka­zo­va­teľ na re­ťa­zec prí­ka­zo­vé­ho riad­ka, kto­rý bol po­uži­tý pri spúš­ťa­ní ap­li­ká­cie (nie­čo po­dob­né ako pa­ra­me­ter char* argv[ ] fun­kcie main v prog­ra­moch pod DOS). Po­sled­ným pa­ra­met­rom je kon­štan­ta nCmdShow (mô­že ich byť aj viac, v ta­kom prí­pa­de tie­to kon­štan­ty od­de­ľu­je­me po­mo­cou bi­to­vé­ho ope­rá­to­ra OR {|}), kto­rá mô­že byť po­uži­tá na ur­če­nie veľ­kos­ti ok­na, je­ho sú­rad­níc a po­dob­ne. Po spus­te­ní prog­ra­mu Hello fun­kcia Win­Main zis­tí, či nie je spus­te­ná iná kó­pia prog­ra­mu. Ako is­te vie­te, vo Win­dows mô­žu bež­ať na­raz aj dve a viac rov­na­kých ap­li­ká­cií. Win­Main to zis­tí prá­ve po­dľa ob­sa­hu hand­le s náz­vom hPre­vIn­stan­ce. Ak sa ne­zis­ti­la prí­tom­nosť ďal­šej ap­li­ká­cie Hello, Win­Main za­re­gis­tru­je no­vú trie­du ok­na (opäť po­zor, nej­de o trie­du, ako ju po­zná­me z C++, v ter­mi­no­ló­gii Win­dows je to ur­či­tý typ ok­na, kto­rý je re­gis­tro­va­ný na po­uži­tie na­šou ap­li­ká­ciou). Re­gis­trá­cia no­vej trie­dy ok­na sa vy­ko­ná­va po­mo­cou fun­kcie Re­gis­terClass, kto­rá je vo­la­ná zvnút­ra blo­ku if(!hPre­vIn­stan­ce) a štruk­tú­ry WNDCLASS. Prá­ve prí­kaz if(!hPre­vIn­stan­ce) za­ru­ču­je, že re­gis­trá­cia trie­dy ok­na sa ne­vy­ko­ná, ak je už rov­na­ká ap­li­ká­cia spus­te­ná (a tá už trie­du ok­na za­re­gis­tro­va­la). V te­le cyk­lu „napĺňa­me“ štruk­tú­ru WNDCLASS dá­ta­mi. Ro­bí­me tak po­mo­cou na­mi dek­la­ro­va­nej štruk­tú­ry wndclass, kto­rá je za­lo­že­ná na štruk­tú­re WNDCLASS (prí­kaz: WNDCLASS wndclass). Na kon­ci toh­to cyk­lu je už spo­mí­na­ná fun­kcia Re­gis­terClass, kto­rá na zá­kla­de zís­ka­ných in­for­má­cií štruk­tú­ry wndclass za­re­gis­tru­je no­vú trie­du ok­na a dá jej me­no (v na­šom prí­pa­de szMe­no). Ak už má­me ok­no za­re­gis­tro­va­né, mô­že­me ho zob­ra­ziť. Naj­prv však mu­sí­me ok­no vy­tvo­riť. Na to slú­ži fun­kcia Crea­teWin­dow. Opis jej pa­ra­met­rov tu ne­bu­dem uvád­zať (mô­že ich mať veľ­mi ve­ľa), náj­de­te ich v prík­la­de Hello a rov­na­ko aj v hel­pe. Tak te­da po tom, ako sme vy­tvo­ri­li ok­no (Crea­teWin­dow), sta­čí ho už len zob­ra­ziť. Na to slú­ži fun­kcia ShowWin­dow, kto­rá ako pa­ra­met­re má ok­no, kto­ré bo­lo vy­tvo­re­né po­mo­cou Crea­teWin­dow (v na­šom prí­pa­de hwnd), a kon­štan­tu nCmdShow (jej opis sme už uvied­li). Po­sled­ná fun­kcia, kto­rú po­uži­je­me, je Up­da­teWin­dow. Tú­to fun­kciu po­uži­je­me vždy, keď chcem ne­ja­kým spô­so­bom zme­niť ob­sah ok­na (pri­pí­sať doň text, zme­niť far­bu po­za­dia a pod.). Fun­kcie Crea­teWin­dow, ShowWin­dow a Up­da­teWin­dow sú API fun­kcie, tak­že nik­de ich ne­mu­sí­me dek­la­ro­vať ani nič po­dob­né.

Po tom, ako Win­Main za­re­gis­tru­je no­vú trie­du pre na­še ok­no, spus­tí hlav­ný uzol správ po­mo­cou kó­du:

whi­le (Get­Mes­sa­ge(&msg, NULL, 0, 0)) {
		Tran­sla­te­Mes­sa­ge(&msg);
Dis­pat­chMes­sa­ge(&msg); }

V na­šom prog­ra­me uzol správ spra­cú­va ope­rá­cie opa­ko­va­ným vo­la­ním fun­kcií Get­Mes­sa­ge, Tran­sla­te­Mes­sa­ge, Dis­pat­chMes­sa­ge. Uzol a zá­ro­veň aj prog­ram sa kon­čí po prev­za­tí sprá­vy WM_QUIT, kto­rú za­šle fun­kcia Po­stQuit­Mes­sa­ge.

Všet­ky tie­to fun­kcie ob­sa­hu­jú ako pa­ra­me­ter štruk­tú­ru msg. Je to opäť ako v prí­pa­de štruk­tú­ry WNDCLASS na­mi dek­la­ro­va­ná štruk­tú­ra (prí­kaz: MSG msg). Fun­kcia Get­Mes­sa­ge po­uží­va tú­to štruk­tú­ru na od­ov­zdá­va­nie in­for­má­cií o sprá­vach. Štruk­tú­ra MSG je de­fi­no­va­ná v sú­bo­re win­dows.h, a pre­to ju tu ne­bu­dem uvád­zať. Uve­diem len opis jej člen­ských pre­men­ných. V pre­men­nej hwnd sú ulo­že­né in­for­má­cie o ok­ne, kto­ré­mu bo­la sprá­va po­sla­ná. V pre­men­nej mes­sa­ge je ulo­že­né čís­lo sprá­vy (aká je to sprá­va). V pre­men­ných wPa­ram a lPa­ram sú ulo­že­né in­for­má­cie o ty­pe uda­los­ti, o kto­rej jej sprá­va, a o zdro­ji, kto­rý uda­losť vy­vo­lal. Obid­ve tie­to pre­men­né sú zá­vis­lé od pre­men­nej mes­sa­ge. Kla­sic­ký prí­pad je, keď uda­losť bo­la spô­so­be­ná stla­če­ním tla­čid­la my­ši, po­tom štruk­tú­ra MSG ob­sa­hu­je v pre­men­nej wPa­ram in­for­má­ciu o tom, kto­ré tla­čid­lo my­ši bo­lo stla­če­né, a v pre­men­nej lPa­ram mô­že byť in­for­má­cia o tom, kto­rý ria­dia­ci klá­ves bol stla­če­ný zá­ro­veň s tla­čid­lom my­ši. V pre­men­nej ti­me je ulo­že­ný čas, keď bo­la sprá­va za­zna­me­na­ná, a v pre­men­nej pt je ulo­že­ná po­zí­cia (sú­rad­ni­ce) kur­zo­ra, keď bo­la sprá­va za­zna­me­na­ná.

TI­PY NA DO­MA
Skús­te si do­ma po­zrieť v sú­bo­re win­dows.h de­fi­ní­ciu štruk­túr MSG a WNDCLASS. Rov­na­ko si v hel­pe po­zri­te pres­ný opis fun­kcií Get­Mes­sa­ge, Tran­sla­te­Mes­sa­ge, Dis­pat­chMes­sa­ge, Crea­teWin­dow, ShowWin­dow, Up­da­teWin­dow a Re­gis­terClass. Za­expe­ri­men­tuj­te s fun­kciou Crea­teWin­dow (zmeň­te po­čia­toč­né nas­ta­ve­nia ok­na, zväč­ši­te ale­bo zmen­ši­te ok­no a pod., skús­te aj nie­čo so štý­lom ok­na).

NA­BUDÚCE
Na­bu­dú­ce si do­kon­čí­me roz­bor prík­la­du Hello a uve­die­me si, ako sa vlas­tne dá do ok­na kres­liť, resp. pí­sať. Opí­še­me si kon­text za­ria­de­ní a GDI ob­jek­ty. Ak nám zos­ta­ne pries­tor, za­čne­me si opi­so­vať aj kniž­ni­cu MFC.

Ďal­šie čas­ti >>

Zdroj: PC Revue 9/2000



Ohodnoťte článok:
   
 

24 hodín

týždeň

mesiac

Najnovšie články

C++ pod Win­dows: 1. časť: Úvod
Vítam vás pri novom seriáli o programovaní. Ako z názvu môžete usúdiť, pôjde o programovanie pod operačným systémom Microsoft Windows využitím jazyka C++. čítať »
 
C++ pod Win­dows: 26. časť: Zá­ver
V tejto časti sa pri seriáli C++ pod Windows stretávame naposledy. Predchádzajúcich 25 častí bolo venovaných čisto programovaniu a riešeniu rôznych programátorských úloh. čítať »
 
C++ pod Win­dows: 25. časť: Ac­ti­veX & DLL
Vítam vás pri predposlednej časti seriálu C++ pod Windows. Či už ju čítate na Slovensku v prehriatej kancelárii, alebo niekde v Karibiku s nohami namočenými v mori čítať »
 
C++ pod Win­dows: 24. časť: How to... II
Čo sme načali v predchádzajúcej časti, tým budeme teraz pokračovať. Pozrieme sa na tlač a komponenty ActiveX. Opäť uplatníme čisto praktický (how-to) prístup čítať »
 
C++ pod Win­dows: 23. časť: How to... I
Vítam vás pri ďalšom pokračovaní seriálu. V predchádzajúcej časti sme dobrali všetko, čo som na začiatku označil ako rozumný základ, po ktorého zvládnutí budete pripravení na získavanie ďalších vedomostí čítať »
 
C++ pod Win­dows: 22. časť: Se­ria­li­zá­cia ap­li­ká­cií MDI
Nastal máj, lásky čas. Dúfam, že keď čítate tieto riadky, počasie sa už umúdrilo a je pekne teplo a slnečno, tak ako sa na máj patrí. čítať »
 
C++ pod Win­dows: 21. časť: Se­ria­li­zá­cia SDI ap­li­ká­cií II.
Vítam vás pri ďalšom pokračovaní nášho rozprávania o programovaní pod Windows. V tejto časti uvedením ukážkového príkladu dokončíme opis serializácie aplikácií SDI. čítať »
 
C++ pod Win­dows: 20. časť: Se­ria­li­zá­cia SDI ap­li­ká­cií I
V tejto časti budeme pokračovať v začatom rozprávaní o serializácii a preberieme si serializáciu aplikácií typu SDI (Single Document Interface). čítať »
 
 
 
  Zdieľaj cez Facebook Zdieľaj cez Google+ Zdieľaj cez Twitter Zdieľaj cez LinkedIn Správy z RSS Správy na smartfóne Správy cez newsletter