C++ pod Windows: 23. časť: How to... I

cplusplus.jpg Ví­tam vás pri ďal­šom po­kra­čo­va­ní se­riá­lu. V pred­chád­za­jú­cej čas­ti sme dob­ra­li všet­ko, čo som na za­čiat­ku ozna­čil ako ro­zum­ný zá­klad, po kto­ré­ho zvlád­nu­tí bu­de­te prip­ra­ve­ní na zís­ka­va­nie ďal­ších ve­do­mos­tí a bu­de­te ta­kis­to schop­ní sa­mos­tat­ne vy­tvá­rať štan­dar­dné ap­li­ká­cie pre Win­dows. V tej­to čas­ti si mô­že­te ove­riť, čo v praxi zna­me­ná „zís­ka­va­nie ďal­ších ve­do­mos­tí“. Len vý­ni­moč­ne to­tiž bu­de­te mať dos­ta­tok ča­su na preš­tu­do­va­nie ne­ja­kej kni­hy ale­bo roz­siah­lej­šej do­ku­men­tá­cie, do­pod­rob­na ro­zo­be­ra­jú­cej kon­krét­ny prob­lém, kto­rý sa sna­ží­te vy­rie­šiť. Ove­ľa čas­tej­šie bu­de­te vy­hľa­dá­vať už je­ho fun­kčné rie­še­nie, čo je ve­ľak­rát rých­lej­šie a jed­no­duc­hšie ako po­kú­ša­nie sa o sa­mos­tat­né rie­še­nie (tre­ba však po­ve­dať, že nie vždy je ta­ké­to hľa­da­nie ús­peš­né). A ta­ký­to prís­tup vám tu te­raz po­nú­kam. Sú to rie­še­nia štan­dar­dných „zá­ky­sov“, s kto­rý­mi sa mô­že­te stret­núť (niek­to­ré som vy­bral z va­šich mai­lov). Ne­bu­dú to vô­bec zlo­ži­té ve­ci, na všet­ky by ste is­tot­ne po ur­či­tom ča­se priš­li aj sa­mi, ale na­čo vy­mýš­ľať nie­čo, čo už bo­lo vy­mys­le­né?

HOW TO ZOB­RA­ZIŤ BI­TMA­PU
Bi­tma­py sa v prog­ra­moch po­uží­va­jú re­la­tív­ne čas­to. Naj­jed­no­duc­hším spô­so­bom, ako zob­ra­ziť bi­tma­pu, je pri­dať ju do zdro­jov v de­sign-ti­me a od­tiaľ ju po­mo­cou štan­dar­dných fun­kcií po­čas be­hu prog­ra­mu na­tiah­nuť a zob­ra­ziť. Vy­tvor­te si štan­dar­dnú SDI ap­li­ká­ciu s Do­cu­ment/View po­dpo­rou. Zá­klad­nú trie­du po­hľa­du od­voď­te od CView. V edi­to­re zdro­jov vy­ber­te z me­nu In­sert -> New Re­sour­ce, klik­ni­te na Bi­tmap (obr. 1) a po­tom na Im­port (za pred­pok­la­du, že bi­tma­pu už má­te vy­tvo­re­nú).

C++_23_obr1.jpg
Obr. 1 Pri­dá­va­nie bi­tma­py do zdro­jov

Na­lis­tu­je a naim­por­tuj­te že­la­nú bi­tma­pu (napr. c:\Win­dows\za­po­tec.bmp). Tá sa te­raz zob­ra­zí v zdro­joch pod náz­vom IDB_BIT­MAP1 (ten mô­že­te zme­niť). V trie­de po­hľa­du vo fun­kcii On­Draw pri­daj­te ten­to kód:

void CBit­map­View::On­Draw(CDC* pDC)
{
	CSi­ze m_si­zeZ­droj;

	CBit­map* pbmpMy­Bit­map;
	CDC* pdcMe­mo­ry;

	BI­TMAP bm;

	pdcMe­mo­ry=new CDC;
	pbmpMy­Bit­map=new CBit­map;

	pbmpMy­Bit­map->Load­Bit­map(IDB_BIT­MAP1);
	pdcMe­mo­ry->Crea­te­Com­pa­tib­leDC(pDC); 
	pdcMe­mo­ry->Se­lec­tOb­ject(pbmpMy­Bit­map);
	pbmpMy­Bit­map->Ge­tOb­ject(si­zeof(bm), &bm);

	// Zis­ka­me roz­me­ry bi­tma­py 
	m_si­zeZ­droj.cx=bm.bmWidth;
	m_si­zeZ­droj.cy=bm.bmHeight; 

	// Za­cho­va vel­kost bi­tma­py (+100 ne­ma ziad­ny vy­znam)
	pDC->Bi­tBlt(0, 0, m_si­zeZ­droj.cx+100, m_si­zeZ­droj.cy+100, pdcMe­mo­ry, 0, 0, SR­CCO­PY); 

	// Umoz­ni zme­nit vel­kost bi­tma­py
	pDC->SetStretchBl­tMo­de(2); 
	pDC->StretchBlt(100, 0, m_si­zeZ­droj.cx+100, m_si­zeZ­droj.cy+100, pdcMe­mo­ry, 0, 0,
 m_si­zeZ­droj.cx, m_si­zeZ­droj.cy, SR­CCO­PY); 

	de­le­te pdcMe­mo­ry;
	de­le­te pbmpMy­Bit­map;
}

C++_23_obr2.jpg
Obr. 2 Vý­stup ap­li­ká­cie na zob­ra­zo­va­nie bi­tmáp

Uve­de­ný kód pred­sta­vu­je len ume­lý (ale funkč­ný) prík­lad, ako zob­ra­ziť v prog­ra­me bi­tma­pu (vý­stup vi­dí­te na obr. 2). V praxi by sa žia­da­lo dek­la­rá­cie pre­men­ných dať do hla­vič­ko­vé­ho sú­bo­ru, alo­ko­vať (new) a uvoľ­niť (de­le­te) pa­mäť do konštruk­to­ra/deš­truk­to­ra a ob­slú­žiť aj ďal­ší ma­po­va­cí re­žim (uve­de­ný prík­lad fun­gu­je správ­ne len v ma­po­va­com re­ži­me MM_TEXT). Skús­te si to.

HOW TO PREH­RAŤ WAV ZVUK
Keď už sme pri zdro­joch, uká­že­me si, ako preh­rať jed­no­duc­hý zvuk (wav – sú­bor). Naj­prv po­uži­je­me fun­kciu Play­Sound (bu­de­me preh­rá­vať pria­mo sú­bor nah­rá­va­ný z dis­ku) a po­tom si uká­že­me po­uži­tie fun­kcie sndPlay­Sound na preh­rá­va­nie zvu­ku zo zdro­jov. Vy­tvor­te no­vú Di­alog-Ba­sed ap­li­ká­ciu a na di­alóg pri­daj­te dve tla­čid­lá: PlayF a PlayR (to sú hla­vič­ky, ID nec­haj­te de­fault). Na­ma­puj­te na ne sprá­vu BN_CLIC­KED a do ob­služ­nej fun­kcie pre tla­čid­lo PlayF (IDC_BUT­TON1) pri­daj­te ten­to kód:

void CSoundDlg::On­But­ton1() 
{
	// preh­ra­va­me pria­mo zo su­bo­ru
	CString sndSound;

	sndSound="c:\\Win­dows Lo­gon Sound.wav";
	Play­Sound(sndSound, NULL, SND_FI­LE­NA­ME); 
}

C++_23_obr3.jpg
Obr. 3 Wav sú­bor v zdro­joch

Aby sme vô­bec moh­li preh­rá­vať ne­ja­ký sú­bor zo zdro­jov, je po­treb­né ho tam naj­prv pri­dať. V edi­to­re zdro­jov vy­ber­te z me­nu In­sert -> Re­sour­ce a po­tom Im­port. Na­lis­tuj­te ho­ci­ja­ký wav sú­bor. Po pri­da­ní sa v edi­to­re zdro­jov vy­tvo­rí no­vá zlož­ka s náz­vom "WAVE" a v nej zdroj IDR_WAVE1 (obr. 3).

Te­raz už mô­že­te pri­dať kód do fun­kcie On­But­ton2:

void CSoundDlg::On­But­ton2() 
{
	// preh­ra­va­me zo zdro­jov
	HRSRC hRes; 
	HGLO­BAL hDa­ta;
	BOOL bOk = FAL­SE;

	if ((hRes = ::Fin­dRe­sour­ce(AfxGet­Re­sour­ce­Hand­le(), MA­KEIN­TRE­SOUR­CE(IDR_WAVE1), 
"WAVE")) != NULL &&
	  (hDa­ta = ::Load­Re­sour­ce(AfxGet­Re­sour­ce­Hand­le(), hRes)) != NULL)
	{
		// preh­ra­me zdroj
		bOk = sndPlay­Sound((LPCSTR)::Loc­kRe­sour­ce(hDa­ta), SND_ME­MO­RY | 
       SND_SYNC | SND_NO­DE­FAULT);
		// uvol­ni­me
		FreeRe­sour­ce(hDa­ta);
	}
	if (!bOk)
		if (!bOk)
			Mes­sa­ge­Box("Chy­ba pri preh­ra­va­ni su­bo­ru.", "Upo­zor­ne­nie", 
       MB_ICONWAR­NING | MB_OK);
}

Fun­kcie Play­Sound a sndPlay­Sound sú dek­la­ro­va­né v sú­bo­re mmsys­tem.h a im­ple­men­to­va­né v sú­bo­re winmm.lib. Pri­daj­te pre­to tú­to in­clu­de di­rek­tí­vu:

#in­clu­de <mmsys­tem.h>

a v nas­ta­ve­niach pro­jek­tu [me­nu Pro­ject -> Set­tings (ALT + F7)] na kar­te Link pri­daj­te kniž­ni­cu winmm.lib (obr. 4).

HOW TO PO KLIK­NUTÍ NA TLA­ČID­LO OD­OB­RAŤ ZO ZOZ­NA­MU PO­LOŽ­KU A PRI­DAŤ JU DO DRUHÉHO ZOZ­NA­MU
Veľ­mi čas­tý prob­lém. Vy­tvor­te si no­vý pro­jekt (MFC AppWizard exe) ty­pu Di­alog ba­sed ap­pli­ca­tion. Všet­ky os­tat­né nas­ta­ve­nia nec­haj­te de­fault. V edi­to­re zdro­jov pri­daj­te na di­alóg ov­lá­da­cie pr­vky, ako vi­dí­te na obr. 5. Ich ID nec­haj­te de­fault.

C++_23_obr4.jpg
Obr. 4 Pri­da­nie kniž­ni­ce do pro­jek­tu

Po­tom vo fun­kcii OnI­nit­Dia­log napl­ňte IDC_LIST1:

CLis­tBox* pLB=(CLis­tBox*) GetDl­gI­tem(IDC_LIST1);

pLB->In­sertString(-1, "1. Po­loz­ka"); 
pLB->In­sertString(-1, "2. Po­loz­ka");
pLB->In­sertString(-1, "3. Po­loz­ka");
pLB->In­sertString(-1, "4. Po­loz­ka");
pLB->In­sertString(-1, "5. Po­loz­ka");

Po­mo­cou Class Wizar­du na­ma­puj­te na tla­čid­lo IDC_BUT­TON1 sprá­vu BN_CLIC­KED. Do te­la ob­služ­nej fun­kcie On­But­ton1 pri­daj­te ta­ký­to kód:

void CListCtrlDlg::On­But­ton1() 
{
	CString str­Se­lec­tion;
	
	CLis­tBox* pLB1=(CLis­tBox*) GetDl­gI­tem(IDC_LIST1);
	CLis­tBox* pLB2=(CLis­tBox*) GetDl­gI­tem(IDC_LIST2);

	// in­dex po­loz­ky, kto­ra je ozna­ce­na
	int in­dex=pLB1->Get­Cur­Sel();

	// ak sme nie­co ozna­ci­li
	if (in­dex!=-1)
	{
		// zis­ka­me text
		pLB1->Get­Text(in­dex, str­Se­lec­tion); 

		// ak uz v List2 exis­tu­je pri­da­va­na
		// po­loz­ka, tak nep­ri­dat
		if ((pLB2->FindString(-1, str­Se­lec­tion))==LB_ERR)
			pLB2->AddString(str­Se­lec­tion); 
		el­se
Mes­sa­ge­Box("Ten­to za­znam uz bol pri­da­ny!", "Upo­zor­ne­nie", 
       MB_ICO­NIN­FOR­MA­TION | MB_OK);
	}
}

HOW TO ZMA­ZAŤ OZNA­ČENÚ PO­LOŽ­KU ZO ZOZ­NA­MU
Vy­uži­je­me pred­chád­za­jú­ci prík­lad. V edi­to­re zdro­jov pri­daj­te eš­te jed­no tla­čid­lo IDC_BUT­TON2 s hla­vič­kou X. Na­ma­puj­te naň sprá­vu BN_CLIC­KED a do ob­služ­nej fun­kcie na­píš­te kód:

void CListCtrlDlg::On­But­ton2() 
{
	CLis­tBox* pLB1=(CLis­tBox*) GetDl­gI­tem(IDC_LIST1);

	// in­dex po­loz­ky, kto­ra je ozna­ce­na
	int in­dex=pLB1->Get­Cur­Sel();

	if (in­dex!=-1)
	{
		// zma­ze­me po­loz­ku
		pLB1->De­le­teS­tring(in­dex);  
	}
}

HOW TO NAK­RES­LIŤ DO DI­ALÓGU NE­JAKÚ GRA­FI­KU
Ak ste prog­ra­mo­va­li vo Vi­sual Ba­si­cu, kres­liť do di­aló­gu sa da­lo jed­no­duc­ho vy­uži­tím ov­lá­da­cích pr­vkov Sha­pe a Li­ne už v de­sign ti­me. Vo Vi­sual C++ však tie­to pr­vky ne­náj­de­te. Kres­liť je mož­né len po­čas be­hu prog­ra­mu (run-ti­me). Naj­vhod­nej­šia fun­kcia na kres­le­nie je fun­kcia On­Paint. Naj­lep­šie je kres­liť do ne­ja­ké­ho ov­lá­da­cie­ho pr­vku (napr. Sta­tic Text). Vy­chád­za­me z to­ho, že ov­lá­da­cí pr­vok je vlas­tne ok­no (po­to­mok trie­dy CWnd), a pre­to mô­že­me doň kres­liť rov­na­ko, ako ke­by sme kres­li­li do ok­na.

C++_23_obr5.jpg
Obr. 5 Di­alóg na ko­pí­ro­va­nie po­lo­žiek med­zi dvo­ma zoz­na­ma­mi

Opäť vy­uži­je­me zdroj di­aló­gu z pred­chád­za­jú­ce­ho prík­la­du. Pri­daj­te na di­alóg ov­lá­da­cí pr­vok Sta­tic Text (ID nec­haj­te de­fault, hla­vič­ku zmaž­te, roz­mer: 158 × 38). Po­tom do fun­kcie On­Paint do vet­vy el­se pri­daj­te nas­le­du­jú­ci kód:

el­se
{
	// de­vi­ce con­text na kres­le­nie
	CPaintDC dc(this); 
			
	// zis­ka­me uka­zo­va­tel na ov­la­da­ci pr­vok, do kto­re­ho chce­me kres­lit
	CWnd* pWnd=GetDl­gI­tem(IDC_STA­TIC);

	// zis­ka­me kon­text za­ria­de­nia
	CDC* pCon­trolDC=pWnd->GetDC();
	
	// po­vie­me mu, ze chce­me don kres­lit
	pWnd->In­va­li­da­te();
	pWnd->Up­da­teWin­dow();

	// kres­li­me
	pCon­trolDC->Se­lec­tStoc­kOb­ject(BLACK_BRUSH);
	pCon­trolDC->Li­ne­To(150, 50);
	pCon­trolDC->Ellip­se(30, 30, 50, 50);
	
	// ne­za­bud­nut uvol­nit kon­text za­ria­de­nia
	pWnd->Re­lea­seDC(pCon­trolDC);		
		
	CDia­log::On­Paint();
}

C++_23_obr6.jpg
Obr. 6 Kres­le­nie do di­aló­gu

Vý­sle­dok vi­dí­te na obr. 6. Sa­moz­rej­me, ne­mu­sí­te kres­liť len do ov­lá­da­cie­ho pr­vku Sta­tic Text, ale nap­rík­lad aj do tla­čid­la, zoz­na­mu atď. (jed­no­duc­ho do všet­ké­ho, čo je od­vo­de­né od CWnd).

HOW TO ZME­NIŤ CAP­TION TLA­ČID­LA ALE­BO JE­HO ĎALŠIE VLAS­TNOS­TI (ROZ­MER, UMIES­TNE­NIE) ZA BE­HU PROG­RA­MU
Rie­še­nie je po­dob­né ako v pred­chád­za­jú­com prí­pa­de. Sta­čí pris­tu­po­vať k ov­lá­da­cie­mu pr­vku ako k ok­nu a po­mo­cou štan­dar­dných fun­kcií zme­niť niek­to­ré vlas­tnos­ti. Uká­že­me si, ako zme­niť hla­vič­ku a umies­tne­nie. Vy­tvor­te no­vý zdroj di­aló­gu a pri­daj­te doň ov­lá­da­cí pr­vok tla­čid­lo. ID nec­haj­te de­fault a hla­vič­ku ta­kis­to. Ďalej pri­daj­te eš­te jed­no tla­čid­lo (to bu­de ini­cio­vať zme­nu). Je­ho ID tiež nec­haj­te de­fault a hla­vič­ku zmeň­te na Chan­ge. Na­ma­puj­te naň sprá­vu BN_CLIC­KED a do te­la ob­služ­nej fun­kcie pri­daj­te kód:

 void CDrawDlg::On­But­ton2() 
{
	//zis­ka­me uka­zo­va­tel na ov­la­da­ci pr­vok tla­cid­la
	CWnd* pWnd=GetDl­gI­tem(IDC_BUT­TON1);

	// nas­ta­vi­me text na tla­cid­le
	pWnd->SetWin­dowText("Moj but­ton");

	// zme­ni­me po­lo­hu tla­cid­la - za­cho­va­me je­ho vel­kost
	pWnd->SetWin­dowPos(&wndTop, 50, 10, 0, 0, SWP_NO­SI­ZE);
}

HOW TO PO­UŽÍVAŤ ŠTAN­DARDNÉ FUN­KCIE NA PRÁCU S REŤAZ­CA­MI, AKO MÁ VB (MID, COM­PA­RE ATĎ.)
Vi­sual Ba­sic má veľ­mi sil­nú po­dpo­ru pre prá­cu s re­ťaz­ca­mi. Op­ro­ti ne­mu sa mô­že zdať po­uží­va­nie céč­kov­ských fun­kcií strcmp, str­cpy... troc­hu zdĺha­vé a zlo­ži­té. Ale aj VC++ (pres­nej­šie MFC) má za­bu­do­va­nú ta­kú­to po­dpo­ru. Tá však nie je prís­tup­ná pre „kla­sic­ké“ re­ťaz­ce (char*). Aby sme ju moh­li vy­uží­vať, je po­treb­né dek­la­ro­vať re­ťaz­ce ako ob­jek­ty od­vo­de­né od trie­dy MFC CString. Prík­lad jej po­uži­tia je tu:

CString str­First;
CString str­Se­cond;

str­First="Ma­ma ma Emu";

// sko­pi­ru­je­me od pia­tej po­zi­cie
str­Se­cond=str­First.Mid(5);
// po­rov­na­me (no ca­se sen­si­ti­ve)
int je­Rov­ne=str­Se­cond.Com­pa­re­No­Ca­se(str­First); 
// hla­da­me po­dre­ta­zec
int na­siel=str­Se­cond.Find("ma"); 
				
cout << (LPCTSTR)str­Se­cond << "\n";
cout << je­Rov­ne << "\n";
cout << na­siel << "\n";
		
// kon­ver­tu­je­me na vel­ke
str­Se­cond.Ma­keUp­per(); 
cout << (LPCTSTR)str­Se­cond << "\n";
// oto­ci­me re­ta­zec
str­Se­cond.Ma­ke­Re­ver­se(); 
cout << (LPCTSTR)str­Se­cond << "\n";
// ko­pi­tu­je­me ob­sah re­taz­ca
str­Se­cond=str­First;
cout << (LPCTSTR)str­Se­cond; 

Sa­moz­rej­me, že fun­kcií na prá­cu s re­ťaz­ca­mi po­sky­tu­je trie­da CString ove­ľa viac, ich zoz­nam náj­de­te v hel­pe.

NA­BUDÚCE
Pr­vú časť How to má­me ús­peš­ne za se­bou. O me­siac sa rov­na­kým štý­lom po­zrie­me na Ac­ti­veX kom­po­nen­ty, kniž­ni­ce DLL, tlač a mož­no aj da­ta­bá­zy. Keď­že sa blí­ži­me k zá­ve­ru se­riá­lu, pý­taj­te sa na ve­ci, čo vám nie sú jas­né (z jed­not­li­vých čas­tí, prí­pad­ne iné prob­lé­my, na aké ste na­ra­zi­li). Mô­žem vám od­po­ve­dať pros­tred­níc­tvom ča­so­pi­su a va­še otáz­ky tak mô­žu po­môcť via­ce­rým či­ta­te­ľom. Do­vi­de­nia v jú­li.

Ďal­šie čas­ti >>

Zdroj: PC Revue 6/2002



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