Image
30.6.2016 0 Comments

C++ pod Windows / How to... II / 24. časť

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

Č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, aj keď pri tlači a ActiveX sa istej dávke teórie nedá vyhnúť.

Tlač a Windows. Tlač v prostredí Windows (aj keď sa to nemusí na prvý pohľad zdať – hlavne tým, čo programovali tlač ešte pod MS DOS) nie je jednoduchá. Ak chceme mať celý tento proces úplne pod kontrolou, musíme dokonale poznať viacero Windows štruktúr a ich obsah a musíme takisto vedieť, ako ich naplniť správnymi údajmi. Našťastie knižnica MFC berie na seba väčšinu týchto činností, čím nám podstatne zjednoduší prácu. V tab. 1 si pozrite funkcie, ktoré MFC využíva na prípravu tlače a na samotnú tlač. Ich podrobný opis nájdete v helpe, najdôležitejšie vlastnosti si uvedieme.

CView::OnPreparePrinting – Ako sa dá pochopiť z jej názvu, táto funkcia len pripravuje tlač a náhľad pred tlačou. Je teda volaná ešte pred týmito operáciami. Jej využitie vidíte v tabuľke 1. Jej ďalšou dôležitou činnosťou je, že zavolá funkciu CView::DoPreparePrinting, ktorá vyvolá štandardný dialóg tlače a vytvorí kontext zariadenia pre tlačiareň (platí pre tlač), resp. vytvorí len samotný kontext zariadenia (platí pre náhľad na tlač).

CView::OnBeginPrinting – Po funkcii OnPreparePrinting  nasleduje práve táto funkcia. Volá sa na začiatku tlače (resp. náhľadu na tlač). Ako jeden z parametrov má ukazovateľ na kontext zariadenia tlačiarne (vytvorený v predchádzajúcej funkcii). Druhým parametrom je ukazovateľ na objekt typu CPrintInfo (podrobne v helpe). CPrintInfo je trieda obsahujúca informácie o práve prebiehajúcom „jobe“ na tlačiarni. 

CView::OnPrepareDC – Funkcia, v ktorej môžete upraviť kontext zariadenia tlačiarne podľa svojich potrieb. Dôležité je, že táto funkcia sa volá pre každú stranu tlače. Pomocou nej môžete teda jednoducho meniť nastavenia tlače pre jednotlivé strany.    

CView::OnPrint – Štandardná implementácia zavolá funkciu OnDraw, ktorej odovzdá ukazovateľ na kontext zariadenia tlačiarne. Rovnako ako predchádzajúca aj táto funkcia sa volá pre každú stránku zvlášť, čo nám umožňuje nastaviť rôzne parametre tlače pre konkrétne strany (číslo strany, ktorá sa práve tlačí, sa dá zistiť pomocou m_nCurPage – členská premenná triedy CPrintInfo. Jeden parameter funkcie OnPrint je ukazovateľ na túto triedu).

CView::OnEndPrinting – Volaná na konci tlače (resp. na konci náhľadu na tlač). Ak sme vytvárali nejaké GDI objekty vo funkcii OnBeginPrinting, je to najlepšie miesto na ich uvoľnenie.

CView::OnDraw – Niekedy okolo ôsmej časti sme si opisovali kontext zariadení systému Windows. Tam sme si len načrtli jeho možnosti a až teraz spoznáme jeho pravú silu. Výstup na tlačiareň urobíme jednoducho tak, že funkciu OnDraw zavoláme s ukazovateľom na kontext zariadenia tlačiarne (napr. z funkcie OnPrint). Všetko, čo doteraz vieme o OnDraw, ostáva v platnosti. To znamená, že ak si v OnDraw nakreslíme nejaký obrázok, ten môžeme poslať na tlačiareň, ak zavoláme OnDraw s ukazovateľom na  kontext tlačiarne alebo na obrazovku, ak OnDraw zavoláme s ukazovateľom na kontext obrazovky. Z toho vyplýva aj používanie funkcie OnDraw na WYSIWYG tlač – stačí nám len „presmerovať“ ukazovateľ na príslušný kontext zariadenia (presný postup si ukážeme v príkladoch, pozri WYSIWYG tlač).

Funkcia

Najčastejšie využitie

CView::OnPreparePrinting

Nastavenie čísla prvej a poslednej strany

CView::OnBeginPrinting

Vytvorenie GDI objektov potrebných na tlač (fonty, štetce...)

CView::OnPrepareDC

Nastavenie špecifických parametrov kontextu zariadenia (napr. mapovací režim) a testovanie konca tlače

CView::OnPrint

Pripravenie dát na tlač a volanie OnDraw (pre WYSIWYG) alebo ich priamy zápis na tlačiareň

CView::OnEndPrinting

Zrušenie GDI objektov

 Tab. 1 – Najdôležitejšie funkcie MFC zabezpečujúce tlač, ktoré môžete prepísať (v poradí podľa volania)

How to WYSIWYG tlač. Predpokladám, že skratka WYSIWYG vám niečo hovorí. Ak nie, tak vedzte, že WYSIWYG je z anglického  What You See Is What You Get. Po preložení do slovenčiny dostanete relatívne presný opis, čo táto skratka vyjadruje. Jednoducho to, čo práve vidíte na monitore, uvidíte aj na výstupnom zariadení (nemusí to byť len tlačiareň). Objekty si zachovajú svoju veľkosť, umiestnenie, farbu a ďalšie atribúty. Ak chceme z nášho programu realizovať WYSIWYG tlač, môžeme tak urobiť jednoducho využitím funkcie OnDraw, ako sme už opísali. V tomto príklade si ukážeme výhody mapovacích režimov s pevnou mierkou (konkrétne MM_TWIPS). Vytvorte nový MFC AppWizard Project s názvom WSWTlac (najlepšie bude, ak si ešte predtým vytvoríte čisté Workspace s názvom napr. TFour a doň budete pridávať všetky tu uvedené príklady). Aplikácia bude typu MDI, triedu pohľadu odvoďte od CScrollView a všetko ostatné nechajte default. Najprv si ukážeme použitie štandardného mapovacieho režimu MM_TEXT. Do triedy CWSWTlacView pridajte súkromnú členskú premennú:

private:

      CRect m_rectArea;

Upravte konštruktor tejto triedy:

// okno 1024x768 pixelov
CWSWTlacView::CWSWTlacView() : m_rectArea(0, 0, 1024, 768) {}

Teraz nastavte rolovacie pásky vo funkcii OnInitialUpdate:

void CWSWTlacView::OnInitialUpdate()
{
      CScrollView::OnInitialUpdate();
 
      CSize sizeTotal(m_rectArea.Width(),  m_rectArea.Height());
      // rolovanie strany
      CSize sizePage(sizeTotal.cx / 2, sizeTotal.cy / 2);
      // rolovanie riadkov
      CSize sizeLine(sizeTotal.cx / 100, sizeTotal.cy / 100);
 
      SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
}

Do funkcie OnDraw dopíšte tento kód:

// 10x napiseme do okna text Ahoj!
// vertikalne posunuty o 20 pixelov
int k=0;
for (int i=0; i<10; i++)
{
      pDC->TextOut(0, k, "Ahoj!");
      k+=20;
}

Pomocou ClassWizardu pridajte do tejto triedy ešte funkcie OnPrepareDC a OnPrint. Do týchto funkcií plus do  OnDraw, OnPreparePrinting, OnBeginPrinting, OnEndPrinting pridajte debug výpisy, aby ste si overili poradie volania. Program spusťte, porovnajte vzhľad textu v okne a v náhľade na tlač (Print Preview). Skúste text aj vytlačiť. Prečo je výstup rozdielny, to sme si podrobne vysvetľovali v ôsmej časti, takže len stručne. Mapovací režim MM_TEXT používa ako svoje jednotky zobrazenia pixely. Pixely sú tzv. súradnice zariadenia, čiže vzhľad výsledného obrázka (resp. strany) závisí od „rozlíšenia“, aké konkrétne zariadenie používa. Jednoduchý príklad je klasické rozlíšenie Windows, keď text bude vyzerať odlišne pri rozlíšení 1024 × 768 a inak pri 800 × 600. V našom prípade sa takto správa tlačiareň. Používa iné rozlíšenie ako Windows, preto je výsledný text zdeformovaný. Po skončení tlače (resp. náhľadu na tlač) by ste mali dostať takéto poradie volaní v debug výpise:

// spustenie aplikácie
CWSWTlacView::OnPrepareDC
CWSWTlacView::OnDraw
// print, resp. print preview
CWSWTlacView::OnPreparePrinting
CWSWTlacView::OnBeginPrinting
CWSWTlacView::OnPrepareDC
CWSWTlacView::OnPrint
CWSWTlacView::OnDraw

Problém zdeformovaného textu pri tlači vyriešime použitím mapovacieho režimu s pevnou mierkou.

Prečo MM_TWIPS. V ôsmej časti sme si o tomto režime povedali len to, že logická jednotka, ktorú MM_TWIPS používa, je 1/1440 palca. Asi teraz nevidíte jeho veľké praktické využitie (veď komu by sa chcelo počítať 1/1440 a ešte k tomu v palcoch!?). Opak je však pravdou. Hovorí vám niečo pojem bod (point)? Väčšina aplikácií používa na vyjadrenie veľkosti textu body (napr. teraz píšem vo Worde s 10-bodovým písmom, nadpis má veľkosť 16 bodov). Výhoda je v tom, že rovnako reprezentuje text aj tlačiareň (t. j. 10-bodové písmo bude 10-bodové na obrazovke aj na tlačiarni. Z toho vyplýva použitie písmen TrueType, ktoré môžu byť zobrazené v ľubovoľnej veľkosti). A práve MM_TWIPS je mapovacím režimom, kde sa ľahko používajú body. Jeden twip je 1/20 bodu (pre úplnosť: jeden bod je 1/72 palca). To znamená, že ak chceme písmo veľkosti 10 bodov, bude to presne 10 × 20, čo je 200 twipov. Twipy si vyskúšame na našej WSWTlac aplikácii. V prvom rade musíme zmeniť konštruktor:

// papier velkosti A4 (21cm x 29.7cm) vyjadreny v twipoch
// 1 palec=2.54 cm, 1 palec=1440 twipov
CWSWTlacView::CWSWTlacView() : m_rectArea(0, 0, 11909, 16804) {}

Zmeňte funkciu SetScrollSizes vo funkcii OnInitialUpdate:

SetScrollSizes(MM_TWIPS, sizeTotal, sizePage, sizeLine);

A nakoniec ešte upravte funkciu OnDraw. Aby sme si prakticky ukázali výhodu MM_TWIPS, použijeme font Times New Roman s veľkosťou 12 bodov. Podrobnejšie informácie o funkcii CreateFont nájdete v helpe.

CFont font;
 
// pouzijeme Times New Roman
// -240 znamena velkost 12 bodov
font.CreateFont(-240, 0, 0, 0, FW_NORMAL, FALSE,
            FALSE, FALSE, ANSI_CHARSET,
            OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
            DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,
            "Times New Roman");  
 
// priradime kontextu zariadenia
CFont* pOldFont=(CFont*) pDC->SelectObject(&font);
     
// 10× napiseme do okna text Ahoj!
// vytvorenym fontom
int k=0;
for (int i=0; i<10; i++)
{
      pDC->TextOut(0, k, "Ahoj!");
      // vertikalny rozostup 16 bodov
      k-=320;
}
 
pDC->SelectObject(pOldFont);

Teraz sa výstupy na obrazovke a na tlačiarni (resp. v náhľade na tlač) už nebudú líšiť. Použitie fontu Times New Roman si môžete vyskúšať aj pri použití mapovacieho režimu MM_TEXT. Uvidíte, že ani vytvorenie fontu s pevnou veľkosťou pomocou funkcie CreateFont problémy režimu MM_TEXT nevyrieši. 

How to tlač bez WYSIWYG. Teraz si predstavme, že nebudeme chcieť realizovať WYSIWYG tlač (t. j. na tlačiarni bude iný výstup, ako máme na obrazovke). Využijeme predchádzajúci príklad. Funkčnosť ostane rovnaká (použitie MM_TWIPS na výpis 10× textu Ahoj! využitím fontu Times New Roman). Teraz však budeme chcieť, aby výstup na tlačiarni nebol tento text, ale ASCII hodnota jednotlivých znakov textu Ahoj!. Ako som uviedol, v tejto situácii sa už  nebudeme môcť spoľahnúť na štandardnú funkciu OnPrint, lebo tá volá funkciu OnDraw a to my nechceme. Budeme teda musieť prepísať túto funkciu a z nej realizovať tlač. Môžete modifikovať predchádzajúci príklad alebo si vytvorte nový projekt. Pre prehľadnosť odporúčam vytvoriť nový projekt. Nazvite ho NWSWTlac a pridajte do Workspace TFour. Vykonajte presne tie isté úpravy ako pri projekte WSWTlac (pre mapovací režim MM_TWIPS). Jediný rozdiel bude, že upravíme ešte aj funkciu OnPrint:

void CNWSWTlacView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
CFont font;
 
      // opat pouzijeme Times New Roman
      // ale velkosti 16 bodov
      // ... ako v OnDraw, prave namiesto
      // hodnoty –240 hodnota –320
 
      // priradime kontextu zariadenia tlaciarne
      CFont* pOldFont=(CFont*) pDC->SelectObject(&font);
 
      // vypiseme ASCII hodnoty
      CString strAhoj="Ahoj!";
      int k=0;
      for (int i=0; i<10; i++)
      {
            CString ascValue;
            int r=0;
            for (int j=0; j<5; j++)
            {
                  ascValue.Format("%d", strAhoj[j]);
                  pDC->TextOut(r, k, ascValue);
                  // rozstupy medzi cislami
                  // 30 bodov
                  r+=600;
            }
            // rozstupy medzi riadkami
            // 16 bodov
            k-=320;
      }    
      pDC->SelectObject(pOldFont);
}

Na obrázkoch 1 a 2 vidíte text na monitore a text v náhľade pred tlačou (čiže aký dostanete, ak stranu vytlačíte). Keď sa nad tým zamyslíte, je to veľmi jednoduché. V OnPrint robíme presne to isté, čo v OnDraw, ibaže ukazovateľ na kontext zariadenia neukazuje na kontext obrazovky, ale tlačiarne.

Obr. 1 Vzhľad strany na obrazovke

Obr. 2  Vzhľad stránky v náhľade pred tlačou

Už teda viete tlačiť z klasickej Document/View aplikácie MFC. Azda sa vám teraz tlač z prostredia Windows zdá celkom jednoduchá. Nuž, možno zdá, ale nie je. Predstavte si aplikáciu nezaloženú na Document/View architektúre (napr. dialógovú aplikáciu). Bum! – všetko, čo ste sa v tejto časti naučili, nemôžete použiť. Na funkcie OnDraw, OnPrint... môžete hneď zabudnúť. Teraz budete musieť sami inicializovať tlačiareň, poslať na ňu dáta, správne ju „uzavrieť“, dať si pozor, aby ste nezmenili defaultnú tlačiareň atď. A verte, nie je to nič jednoduché (pozrite si v helpe topic Printing and Print Spooler Functions a pochopíte).

KOMPONENTY ActiveX. Mnohí ste už asi termín ActiveX počuli, určite ste aj nejaké komponenty ActiveX využívali. Možno však dobre nerozumiete, čo sa pod týmto pojmom skrýva. Tu je jedna z mnohých definícií: ActiveX je skupina technológií, ktorá umožňuje navzájom komunikovať softvérovým komponentom v sieťovom prostredí  bez ohľadu na jazyk, v ktorom boli naprogramované. ActiveX je založené na technológii COM (Component Object Model).  Programátori, ktorí zažili Windows 3.1 a boom technológie OLE, budú teraz isto namietať, že táto definícia nehovorí o ActiveX, ale o OLE. Sčasti majú aj pravdu. V každom prípade je dobré si uvedomiť rozdiel medzi ActiveX a OLE. Nie je pravda, že ActiveX je nasledovník OLE, ani to, že OLE je už zastarané. ActiveX aj OLE sú založené na tej istej technológii – COM (len na okraj: COM je základný objektový model, ktorý umožňuje objektu preniesť svoju funkcionalitu na iný objekt, resp. hostiteľskú aplikáciu). OLE je skratka pre Object Linking and Embedding [čiže spájanie a vkladanie objektov – napr. vo Worde môžete mať tabuľku z Excelu – to je OLE, nie ActiveX (pozor, nepliesť s Active Document Containment technológiou!)]. Všetko ostatné, čo sa netýka spájania a vkladania objektov, sa teraz nazýva tzv. Active technology (ActiveX). V princípe by sa dalo povedať, že ActiveX je vlastne „sieťové OLE“, to však nie je stopercentne presné. Pre lepší prehľad odporúčam v MSDN helpe pozrieť topic: OLE defined, OLE Background , Active Technology Topics , Active document containment, ATL Article Overview -> Introduction to COM and ATL. Pochopiť všetky tieto technológie nie je jednoduché a určite to je záležitosť na viac ako pár týždňov. To vás tento seriál nenaučí. Naučí vás však používať komponenty ActiveX vo vašich aplikáciách. ActiveX sú primárne písané tak, aby ten, kto ich chce použiť, nemusel ovládať všetky detaily COM-u, dokonca aby len vedel, čo to COM je. Ako na to? To si povieme až nabudúce.

Nabudúce. V ďalšej časti si dokončíme a na príklade ukážeme použitie komponentov ActiveX a opíšeme si prácu s  knižnicami DLL. Celé leto je pred nami, prajem vám teda veľa pokoja, oddychu a pekné dovolenky.

Zobrazit Galériu

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

Mohlo by Vás zaujímať

ITPro

Linux súkromne i pracovne v2.0 (14. časť): Small Business Server

09.11.2016 14:57

Pojem Small Business Server (malý firemný server) začala používať spoločnosť Microsoft ešte v roku 2000 na označenie servera, ktorý ­dokázal plniť úlohy niekoľkých samostatných serverov. Aplikačná vrs ...

ITPro

Industry 4.0: Fikcia alebo už realita?

09.11.2016 14:52

Štvrtá priemyselná revolúcia je pomenovanie rozsiahlych zmien prudko vstupujúcich do súčasného priemyslu. Nositeľom týchto zmien je digitalizácia výroby a optimalizácia všetkých podnikových procesov v ...

ITPro

Vývoj aplikácií UWP pre Xbox One II.

09.11.2016 14:47

V predošlej časti sme ukázali postup, ako si ­vytvoriť vývojársky účet a aktivovať vývojársky režim na hernej konzole Xbox One, aby ste mohli testovať svoje aplikácie. Výhodou hernej konzoly Xbox je v ...

Žiadne komentáre

Vyhľadávanie

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

Najnovšie videá