Image
22.6.2016 0 Comments

C++ pod Windows / Knižnica Microsoft Fundation Class / 4. časť

Späť na úvod >> Späť na programovanie >> Späť na seriál

Pred mesiacom sme si dokončili opis „klasického“ programovania vo Windows, ktorému sme venovali prvé tri časti seriálu. V nasledujúcich častiach sa budeme venovať knižnici Microsoft Fundation Class (MFC). Niektorí ste mi písali, že máte problémy s prekladačom. Chápem, nie všetci môžete obetovať zopár desiatok tisíc korún na nákup najnovšej verzie Visual C++ či C++ Buildera. Ale inak to skutočne nejde.

Keď som sa dávnejšie zamýšľal nad tým, o čom by som vlastne chcel písať, došiel som práve k C++. Jednak preto, že C++ je skutočným jazykom profesionálov, je v ňom písaná drvivá väčšina aplikácií a myslím si, že ešte dlhý čas bude C++ hrať v tejto oblasti prvé husle. Lenže na programovanie „profesionálnych“ aplikácií potrebujete aj „profesionálne“ vývojové prostredie, ktoré sa nedá zohnať za pár korún a určite sa nedá zadarmo stiahnuť z internetu. Mohol som písať o programovaní vo Windows „starým“ spôsobom (API programovaním), ako to bolo v prvých troch častiach seriálu. Mohli by ste si síce preložiť všetky ukážkové aplikácie uvedené v seriáli, dokonca by ste sa takto naučili aj slušne programovať a bezpochyby by ste vytvorili aj nejaký ten „programík“. Keby ste však začali písať „skutočné“ aplikácie, rýchlo by ste pochopili, že programovanie pomocou API vám neposkytuje veľký komfort, museli by ste ovládať obrovské množstvo funkcií, nehovoriac o ešte väčšom množstve rôznych parametrov a podobne. Zase by ste teda skončili pri štúdiu nejakej knižnice, ako je MFC. Dospel som k takémuto záveru: keď sa už učiť programovať vo Windows v C++, tak takým spôsobom, aby ste svoje vedomosti mohli zužitkovať pri tvorbe aplikácií, ktoré by ste mohli aj nejako využívať, a nie aby slúžili len vám na vlastné potešenie, že ste niečo naprogramovali. Aby som to uzavrel, na učenie sa programovať v C++ s knižnicou MFC je podľa môjho názoru najvhodnejší produkt Microsoft Visual C++ (je jedno, v akej verzii). Preto sa náš seriál bude venovať práve tomuto prostrediu. Samozrejme, príklady by mali byť funkčné aj v C++ Builderi, ale z priestorových príčin nemôžem dopodrobna opisovať obidve prostredia. Ak budete mať otázky ohľadom C++ Buildera, rád vám odpoviem (ak mi to vedomosti dovolia) prostredníctvom e-mailu.

Rád by som sa vrátil k predošlým častiam seriálu. Veľmi ma zamrzelo, keď som si čítal prvú časť. Ako ste si určite všetci všimli, v príklade programu „Hello world“ je chyba, a síce chýbajú ukončovacie úvodzovky vo volaní funkcie printf. Urobiť chybu v programe „Hello world“, navyše v jazyku C je priam hriech, za čo sa vám čitateľom i celému programátorskému svetu ospravedlňujem. Dúfam, že príklad Hello z druhej časti sa vám podarilo úspešne preložiť. Ak ste ho prekladali pod novšími Visual C++ prekladačmi, kompilátor vám vypísal jedno alebo viac varovných hlásení. Bolo to preto, lebo príklad Hello je 16-bitová aplikácia a používa aj nejaké staršie dátové typy, preto tie varovania. Ale program sa dal úspešne spustiť. Chcel som začať úplne od začiatku, čo predstavuje začať 16-bitovým programovaním. Všetky ďalšie príklady budú už 32-bitové a v neskorších častiach sa dostaneme k rozdielom 16- a 32-bitových aplikácií. K druhej časti ešte jedna poznámka. Pri konci, keď opisujem registráciu triedy okna, som sa zle vyjadril ohľadom štruktúry WNDCLASS. Píšem tam, že príkazom WNDCLASS wndclass deklarujeme štruktúru. To, samozrejme, nie je celkom pravda, pretože tento príkaz predstavuje len deklaráciu premennej wndclass typu štruktúra. Rovnako to bolo aj v prípade štruktúry MSG. Takéto chybičky by sa nemali vyskytovať a sľubujem vám, že urobím všetko preto, aby sa už neobjavili. Teraz sa však vráťme ku knižnici MFC.

MICROSOFT FUNDATION CLASS LIBRARY. História knižnice MFC je dosť dlhá a vskutku aj zaujímavá. Ale o tom na inom mieste. Prečo vznikla, to sme si už povedali v prvej časti seriálu. A akú funkciu táto knižnica plní? Na zjednodušenie si predstavte akýsi obal (niekedy sa knižnici MFC hovorí aj objektový wrapper od ang. slova wrap – baliť), ktorý obaľuje API funkcie systému Windows. Napríklad ak pracujete s kontextom zariadení, netreba vám už prácne zisťovať handle kontextu zariadení, jednoducho vytvoríte objekt (teraz už skutočný objekt jazyka C++, nie objekt Windows) kontextu zariadení a pomocou tohto objektu zavoláte príslušnú členskú funkciu triedy (opäť ide o skutočnú triedu jazyka C++) kontextu zariadení a je po probléme. Keď programujete s knižnicou MFC, nebudete musieť v takej miere (ak vôbec budete musieť) využívať handle. Väčšinou zadefinujete len ukazovateľ na nejaký objekt a ten sa už postará o všetko potrebné. Knižnica MFC má vlastné triedy na prácu s oknami, dialógmi, kontextom zariadení, rôznymi GDI objektmi a inými prvkami systému Windows. Ale samotná knižnica a jej aplikačný systém majú oveľa viac výhod ako len zjednodušovať programovanie vo Windows. Napríklad vďaka dynamicky linkovaným knižniciam (DLL) sú aplikácie aplikačného systému rýchle a zaberajú málo priestoru na pevnom disku, ako aj v pamäti (dynamicky linkovaným knižniciam bude venovaná niektorá ďalšia časť seriálu). Ďalšou výhodou môže byť napríklad ucelená štruktúra kódu. Každý programátor má vlastnú formu písania kódu. Používa iné mená pre členské premenné, pre statické premenné, inak zapisuje príkazy typu if...then...else a podobne. Ak potom príde nový člen do programátorského tímu, ten nemusí rozumieť kódu, ktorý napísal niektorý z jeho kolegov. A práve aplikačný systém dodáva akúsi formu vášmu kódu a tým sú tieto problémy z minulosti zažehnané. Mohol by som vám ešte dlho písať o rôznych výhodách používania MFC, ale nemalo by to veľký význam a som presvedčený o tom, že ak budete do tajov MFC prenikať čoraz hlbšie, tieto výhody sami spoznáte.

APLIKAČNÝ SYSTÉM. Už som spomínal aplikačný systém (application framework). Ale čo to vlastne je? Aplikačnému systému sa inak hovorí aj kostra aplikácie. Aby ste nepovedali, tu máte jednu definíciu: „Aplikačný systém je integrovaný súhrn objektovo orientovaných softvérových komponentov, zahrnujúci všetko na vytvorenie všeobecnej aplikácie.“ J Predpokladám, že rovnako ako mne vám táto definícia veľmi nepomohla. Rozdiel medzi samotnou knižnicou MFC a aplikačným systémom je malý. Ak by sme to chceli jednoducho vysvetliť, povedali by sme, že všetky triedy knižnice MFC tvoria aplikačný systém, na ktorom „staviate“ vašu aplikáciu. Aplikačný systém je vlastne kostrou aplikácie s podporou pre komponenty používateľského rozhrania, ktoré môžete pridávať na vytvorenú kostru aplikácie. Tieto komponenty používateľského rozhrania sú napríklad stavový riadok, panel nástrojov, podpora databáz a ActiveX komponentov.

HISTÓRIA MFC  (Z POHĽADU VISUAL C++). Teraz vás čaká história MFC. Je to trochu nudné čítanie, ale získate aspoň aký-taký prehľad o tejto knižnici. Pravdepodobne vám väčšina informácií bude cudzia, ale sľubujem, že sa pokúsim do skončenia seriálu väčšinu z nich vysvetliť tak, aby ste ich mohli aktívne využívať vo vašich aplikáciách. O MFC sa začalo hovoriť na začiatku 90. rokov. Prvá verzia MFC uzrela svetlo sveta spolu s prostredím Microsoft C/C++ verzie 7.0. Už vtedy obsahovala všeobecné triedy, napríklad  triedu kolekcií (collections), zoznamov (lists), máp (maps) a polí (arrays). Obsahovala triedy pre prácu s reťazcami, časovými údajmi, prístup k súborom, triedy pre podporu „viacdokumentových“ MDI (Multiple Document Interface) aplikácií a čiastočne podporovala aj OLE verzie 1.0. Prvý Visual C++ mal integrovanú MFC verzie 2.0. Táto verzia MFC pridávala do predchádzajúcej veľa nových čŕt, ako sú podpora DLL, kontextovej pomoci, prístup k ovládacím prvkom Visual Basicu (VBX controls) a mnohé iné. MFC 2.5 dodávaná s Visual C++ 1.5 mala podporu pre databázy ODBC (Open Database Connectivity), takže programátori mohli jednoducho pristupovať k databázam napríklad Microsoft Access, Microsoft SQL Server a iným. Rovnako sa zlepšila podpora OLE 2.01. Techniky  drag and drop a OLE Automation už neboli len snom vývojárov. Prvá 32-bitová verzia Visual C++ bola verzia 2.0. S ňou prišla aj MFC verzie 3.0. Podporovala napríklad tabuľku vlastností (property sheet), dokovateľné panely nástrojov a takzvaný Control Development Kit (CDK) na vytváranie ovládacích prvkov OLE. Visual C++ 2.1 s MFC verzie 3.1 rozšírilo podporu databáz – ODBC level 2 –, podporu spoločných ovládacích prvkov Windows 95 a obsahovala aj triedu Winsock na komunikáciu TCP/IP. Keby ste hľadali Microsoft Visual C++ 3.0, hľadali by ste márne. Microsoft sa totiž rozhodol, že verzie knižnice MFC a produktov Visual C++ sa musia zhodovať, a preto sa pokračovalo až Visual C++ verziou 4.0MFC 4.0. Novými prvkami boli triedy OLE založené na Data Access Objects (DAO), podpora kontajnerov ovládacích prvkov OLE, triedy na synchronizáciu vlákien, úplná podpora spoločných ovládacích prvkov Windows 95, nové triedy tree view a rich-edit view. Ďalšia verzia bola MFC 4.2, dodávaná s Visual C++ 4.2. Obsahovala triedu WinInet, triedy serverov ActiveX, synchrónne a asynchrónne monikerové triedy ActiveX a bola zlepšená podpora ODBC. Visual C++ 5.0 obsahoval MFC verzie 4.21, ktorá opravovala chyby verzie 4.2 a pridávala podporu jazyka C++ pre klientske programy COM (Component Object Model) spolu s novým príkazom #import. Visual C++ 6.0 obsahuje MFC 6.0. Táto verzia MFC obsahuje nové triedy na prácu so sieťou internet, nové triedy na spracovanie dátumu a rôzne triedy na rozšírené spracovanie niektorých ovládacích prvkov.

Príklad. Tento príklad je ukážkou použitia aplikačného systému. Všimnite si, že triedy knižnice MFC a od nej odvodené sa začínajú podľa konvencií písmenom C.

Výpis súboru first.h

// trieda aplikácie
class CFirstApp : public  CWinApp
{
public:
      virtual BOOL InitInstance();
};
 
// trieda hlavného rámcového okna aplikácie
class CMyFrame : public CFrameWnd
{
public:
      CMyFrame();
protected:
      // afx_msg označuje, že funkcia OnPaint je súčasťou spracúvania správ MFC
afx_msg void OnPaint();
      DECLARE_MESSAGE_MAP()
};
Výpis súboru first.cpp
#include <afxwin.h>     // hlavičkový súbor knižnice MFC deklaruje základné triedy
#include "prvy.h"       // vloženie našich tried
 
CFirstApp first;  // globálny objekt aplikácie
 
BOOL CFirstApp::InitInstance()     // volá funkcie na vytvorenie a zobrazenie rámcového okna aplikácie
{
      m_pMainWnd=new CMyFrame;     // volá konštruktor CMyFrame::CMyFrame
      m_pMainWnd->ShowWindow(m_nCmdShow); 
 
      m_pMainWnd->UpdateWindow();
      return TRUE;
}
BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)   // mapa správ
      ON_WM_PAINT()
END_MESSAGE_MAP()
 
CMyFrame::CMyFrame()
{
      Create(NULL, "Program Hello");     // vytvorí hlavné rámcové okno aplikácie + titulok okna
}
 
void CMyFrame::OnPaint()     // „kresliaca funkcia“ spracúva správu WM_PAINT
{
      CPaintDC dc(this);      // vytvára kontext zariadení na kreslenie
      CRect rectMax;    // premenná ukladá veľkosť klientskeho okna
      CPen pen(PS_SOLID, 6, RGB(0, 0, 255));   // vytvára objekt pera – ekvivalent API funkcie CreatePen
      GetClientRect(rectMax); // do premennej rectMax sa uloží rozmer klientskeho okna
      dc.SelectObject(&pen);  // vyberie uložený GDI objekt a nastaví objekt pera ako aktuálny GDI objekt
      dc.TextOut(0, 0, "Hello, world!"); // vypíše text na obrazovku
      dc.Ellipse(rectMax);    // na obrazovku nakreslí kružnicu tak, aby vypĺňala celé klientske okno
      dc.SelectStockObject(WHITE_BRUSH); // vyberie objekt pera pen a nastaví systémové biele pero
}

Vysvetlenie programu First. Pozrite sa teraz na príklad Hello z druhej časti seriálu. Program je napísaný úplne inak, ale v skutočnosti robí to isté. V prvej časti seriálu som písal, že každý program pre Windows musí obsahovať funkciu WinMain. Ale program First na prvý pohľad túto funkciu nemá. Funkcie ako WinMain, WndProc, GetMessage a podobne sú začlenené do aplikačného systému, teda práve do tej kostry aplikácie, a preto ich už nemusíte písať a sú „pripojené“ ku každému vášmu programu (v nasledujúcej časti si podrobne opíšeme proces zostavovania aplikácie). Trieda CFirstApp reprezentuje aplikáciu. Je odvodená od triedy MFC CWinApp, ktorá je základnou triedou klasickej aplikácie založenej na knižnici MFC. Objekt first je globálnym objektom aplikácie a je dôležitý pri spúšťaní aplikácie. Pri spustení aplikácie hľadá vstavaná funkcia WinMain globálne vytvorený objekt aplikácie triedy odvodenej od triedy CWinApp (v našom prípade objekt first). Uvedomte si, že globálne tvorené objekty sú vytvárané pred spustením hlavného programu. Ak funkcia WinMain tento objekt nájde, volá virtuálnu členskú funkciu InitInstance, ktorá sa postará o vytvorenie a zobrazenie hlavného rámcového okna aplikácie. Túto funkciu musíte vo vašej odvodenej triede prepísať, lebo základná funkcia InitInstance, ktorá je členskou funkciou triedy CwinApp, nevie, aký typ rámcového okna chcete. Po tom, ako WinMain zavolala funkciu InitInstance, volá funkciu Run, čo je členská funkcia triedy CWinApp. Túto funkciu nevidíte, opäť je skrytá v aplikačnom systéme. Je to však veľmi dôležitá funkcia a jej úlohou je doručovať správy aplikácie oknám aplikácie. V jej tele sú funkcie TranslateMessage, DispatchMessage, PreTranslateMessage. Správa sa teda podobne ako uzol správ klasickej aplikácie založenej na Windows API. Ak dostane správu WM_QUIT, ukončí aplikáciu. Ak naša aplikácia dostane správu WM_PAINT, volá obslužnú funkciu OnPaint. Funkcia OnPaint je volaná vždy, keď je potrebné prekresliť okno. To znamená vtedy, keď používateľ zmenil veľkosť okna, keď sa aplikácia štartuje, keď je určitá časť okna zakrytá a znovu odokrytá. Príkaz CPaintDC dc(this) má podobnú funkciu ako vám už známy príkaz BeginPaint (GDI objektom knižnice MFC bude venovaná niektorá ďalšia časť seriálu). Objekt typu CRect je podobný API štruktúre RECT a je to pravouholník, ktorého súradnice zadávame v poradí left, top, right, bottom (pričom left a top sú súradnice ľavého horného rohu pravouholníka a right a bottom sú súradnice pravého dolného rohu pravouholníka). Objekt pen nerušíme funkciou DeleteObject, ale využijeme menší fígeľ. Systém Windows obsahuje množstvo tzv. GDI objektov systémového zásobníka. Tieto GDI objekty dokáže aj sám zrušiť. Funkcia SelectStockObject vyberie z kontextu zariadení objekt pera pen, zároveň vráti ukazovateľ na vynímaný objekt  a nastaví GDI objekt systémového zásobníka WHITE_BRUSH ako aktuálny GDI objekt. My sa už teda nemusíme starať o rušenie tohto objektu WHITE_BRUSH.

Tipy na doma. V helpe si pozrite triedu CWinApp a jej členské funkcie a premenné. Zistite niečo o dátovom člene  m_pMainWnd a triede CFrameWnd a o jej členských funkciách.

Nabudúce. O mesiac si opíšeme proces zostavovania aplikácie pre Windows (proces kompilovania, linkovania), opíšeme si nové typy súborov, ktoré sa vyskytujú v programoch pre Windows. Dokončíme si rozbor príkladu First, zároveň aj príklad First zdokonalíme a povieme si niečo o mapách správ.


Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

Ako na to

Ako funguje sandbox?

08.12.2016 15:36

Každá aplikácia môže pre operačný systém počítača či mobilného zariadenia predstavovať potenciálnu hrozbu, a to aj v prípade, ak neobsahuje žiadne bloky škodlivého kódu. Murphyho zákony neúprosne defi ...

Ako na to

Tipy a triky: Ako na snímku obrazovky na akomkoľvek počítači s Windows?

02.12.2016 00:13

Ak snímky obrazovky robíte často apotrebujete napríklad funkcie na posun stránok alebo snímanie zobrazenia pri vyššom rozlíšení displeja, zrejme používate nejakú špecializovanú aplikáciu. Väčšina použ ...

Ako na to 1

Tipy a triky: Ako aplikácii prednastaviť spúšťanie s administrátorskými právami?

30.11.2016 00:10

Väčšina aspoň trochu skúsenejších používateľov vie, že aj keď máte na operačnom systéme Windows vytvorený administrátorský účet, aplikácie pre bezpečnosť nefungujú vždy splnými administrátorskými práv ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá