GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru =...

Click here to load reader

  • date post

    05-Feb-2018
  • Category

    Documents

  • view

    222
  • download

    0

Embed Size (px)

Transcript of GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru =...

  • 1

    GDI Biblioteca GDI32.DLL GDI = permite manipularea elementelor grafice independente de dispozitiv, este un sistem de afisare static, ce permite numai animatii simple; Dipozitive grafice de iesire:

    1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, imprimante matriciale, laser);

    2. dispozitive vectoriale = deseneaza imaginile prin linii = plottere; Sistem de coordonate virtual, sistem de coordonate al dispozitivului; W95 foloseste coordonate in numere intregi pe 16 biti, W_NT foloseste coordonate pe 32 biti; Din pdv al programatorului, interfata GDI este formata din citeva sute de rutine si unele tipuri de date, macroinstructiuni si structuri de date; Tipuri de apeluri de functii

    Functii care obtin (sau creaza) si elibereaza (sau distrug) un context de dispozitiv; (in API: BeginPaint ... EndPaint, GetDc, ReleaseDC; in MFC (clase): CDC, CPaintDC, CClientDC, CMetaFileDC, CWindowDC)

    Functii care obtin informatii despre contextul de dispozitiv - structura TEXTMETRICS, GetTextMetrics;

    Functii care deseneaza ceva (TextOut, DrawText, desenarea liniilor, a zonelor colorate si a imaginilor bitmap...);

    Functii care stabiliesc sau obtin atribute ale contextului de dispozitiv - Un atribut al DC specifica modul de lucru al functiilor de desenare; SetTextColor,... Toate atributele DC au valori prestabilite care devin active la obtinerea DC. Pentru fiecare functie de tip Set exista si o functie de tip Get, folosita pt. obtinerea valorilor curente ale atributelor DC.

    Functii care lucreaza cu obiecte GDI; Primitive GDI

    Linii si curbe: linii drepte, dreptunghiuri, elipse, arce. Liniile sint desenate folosind penita (HPEN, clasa CPen) curenta selectata in DC

    Suprafete pline: Suprafata poate fi umpluta folosind pensula GDI curenta (HBRUSH, clasa CBrush)

    Imagini bitmap: matrici dreptunghiulare de biti, care corespund pixelilor unui dispozitiv de afisare - pt. sisteme grafice de tip rastru. Imagini bitmap - dependente de dispozitiv si imagini bitmap independente de dispozitiv (DIB = Device Independent Bitmap) care pot fi stocate in fisiere.

    Text: afisarea textului este legata de fonturi (HFONT, clasa CFont). Alte aspecte ale GDI:

    Moduri de mapare si transformari: sitem de coordonate in pixeli, inci, mm Metafisiere (metafiles): o colectie de comenzi GDI stocate intr-o forma binara;

    sint folosite pentru transferarea reprezentarilor unor elemente grafice vectoriale prin intermediul memoriei temporare (clipboard).

  • 2

    Cai (paths): colectie de linii drepte si curbe stocate intern de GDI; pot fi folosite pt. desenare, umplere sau decupare.

    Decupare (clipping): desenarea poate fi limitata la o anumita sectiune a zonei client, numita zona de decupare - definita in general de o cale sau de o regiune.

    Tiparire (printing):

    Contextul de dispozitiv (DC): Modalitati de obtinere a variabilei handle a DC:

    Varainata 1(putem desena numai in regiunea invalida a ferestrei): la tratarea mesajului WM_PAINT:

    PAINTSTRUCT ps;

    hdc = BeginPaint (hwnd, &ps);

    ...

    EndPaint(hwnd, &ps);

    structura PAINTSTRUCT contine o structura de tip RECT rcPaint; care defineste dreptunghiul ce cuprinde regiunea invalida a zonei client a ferestrei; se valideaza regiunea invalida.

    Varianta 2 (putem desena in toata zona client a ferestrei; nu se valideaza regiunea invalida ale zonei client):

    hdc = GetDC(hwnd);

    ...

    ReleaseDC(hwnd, hdc);

    Varianta 3: (DC cuprinde in plus bara de titlu a ferestrei, barele de derulare si chenarul)

    hdc = GetWindowDC(hwnd);

    ...

    ReleaseDC(hwnd, hdc);

    Pentru folosirea acestei functii trebuie interceptat mesajul WM_NCPAINT ( non client paint).

    Varianta 4: CreateDC

    hdc = CreateDC(pszDriver, pszDevice, pszOutput,

    pData);

    ...

    DeleteDC(hdc);

    Pentru a obtine o variabila handle a DC pt. spatiul de afisare: hdc = CreateDC(DISPLAY, NULL, NULL, NULL);

  • 3

    Varianta 5: Obtinere informatii despre DC - CreateIC care are aceeasi parametri ca si CreateDC

    hdc = CreateIC(pszDriver, pszDevice, pszOutput,

    pData);

    ...

    DeleteDC(hdc);

    Varianta 6: context de dispozitiv in memorie - necesar la lucrul cu imagini

    bitmap:

    hdcmem = CreateCompatibleDC (hdc)

    ...

    DeleteDC(hdcMem);

    Crearea unui metafisier:

    hdcMeta = CreateMetaFile(pszFileName);

    ...

    hmf = CloseMetaFile(hdcMeta);

    Obtinere informatii despre contextul de dispozitiv: dimensiuni ecran (pixeli, fizice) posibilitati de folosire a culorilor, etc. cu functia GetDeviceCaps (get device capabilities); ivalue = GetDeviceCaps(hdc, iIndex);

    Atributele Contextului de Dispozitiv

    Cele mai uzuale atribute ale DC sunt date in urmatorul tabel:

    Attribute Default Set with Get with Text color Black CDC::SetTextColor CDC::GetTextColor Background color White CDC::SetBkColor CDC::GetBkColor Background mode OPAQUE CDC::SetBkMode CDC::GetBkMode Mapping mode MM_TEXT CDC::SetMapMode CDC::GetMapMode Drawing mode R2_COPYPEN CDC::SetROP2 CDC::GetROP2 Current position (0,0) CDC::MoveTo CDC::GetCurrentPosition Current pen BLACK_PEN CDC::SelectObject CDC::SelectObject Current brush WHITE_BRUSH CDC::SelectObject CDC::SelectObject Current font SYSTEM_FONT CDC::SelectObject CDC::SelectObject

    GDI Moduri de desenare functia SetROP2 Mod de desenare Operatii executate

    R2_NOP dest = dest R2_NOT dest = NOT dest

  • 4

    R2_BLACK dest = BLACK R2_WHITE dest = WHITE R2_COPYPEN dest = src R2_NOTCOPYPEN dest = NOT src R2_MERGEPENNOT dest = (NOT dest) OR src R2_MASKPENNOT dest = (NOT dest) AND src R2_MERGENOTPEN dest = (NOT src) OR dest R2_MASKNOTPEN dest = (NOT src) AND dest R2_MERGEPEN dest = dest OR src R2_NOTMERGEPEN dest = NOT (dest OR src) R2_MASKPEN dest = dest AND src R2_NOTMASKPEN dest = NOT (dest AND src) R2_XORPEN dest = src XOR dest R2_NOTXORPEN dest = NOT (src XOR dest)

    Moduri de mapare functia SetMapMode Mod de mapare Distanta ce corespunde la o

    unitate logica Axa x Axa y

    MM_TEXT Pixel spre dreapta in jos MM_LOMETRIC 0,1 mm spre dreapta in sus MM_HIMETRIC 0,01 mm spre dreapta in sus MM_LOENGLISH 0.01 inci spre dreapta in sus MM_HIENGLISH 0.001 inci spre dreapta in sus MM_TWIPS 1/1440 inci spre dreapta in sus MM_ISOTROPIC arbitrar (x = y) Selectabil selectabil MM_ANISOTROPIC Arbitrar (x!=y) Selectabil Selectabil

    Vizorul si fereastra SetWindowExt seteaza extensia ferestrei marimea dorita a ferestrei in unitati logice. SetViewportExt seteaza extensia vizorului marimea in pixeli a ferestrei in care desenam.. Marimea fereastrei este masurata in unitati logice. Marimea viewport-ului este masurata in unitati de dispozitiv, sau pixeli. In modul MM_ISOTROPIC ordinea de apel este SetWindowExt si apoi SetViewportExt. Exemple de cod CRect rect;

    GetClientRect (&rect);

    dc.SetMapMode (MM_ANISOTROPIC);

    dc.SetWindowExt (500, 500);

  • 5

    dc.SetViewportExt (rect.Width (), rect.Height ());

    dc.Ellipse (0, 0, 500, 500); Originea este in coltul din stanga sus. CRect rect;

    GetClientRect (&rect);

    dc.SetMapMode (MM_ANISOTROPIC);

    dc.SetWindowExt (500, -500);

    dc.SetViewportExt (rect.Width (), rect.Height ());

    dc.Ellipse (0, 0, 500, -500); Modul MM_ISOTROPIC CRect rect;

    GetClientRect (&rect);

    dc.SetMapMode (MM_ISOTROPIC);

    dc.SetWindowExt (500, 500);

    dc.SetViewportExt (rect.Width (), rect.Height ());

    dc.Ellipse (0, 0, 500, 500); Pentru vizor se folosesc coordonatele de dispozitiv (pixeli). Pentru toate modurile de mapare, Windows transforma coordonatele ferestrei (coordonate logice) in coordonate ale vizorului (coordonate de dispozitiv) folosind doua formule: xViewport = (xWindow - xWinOrg) * (xViewExt / xWinExt) + xViewOrg yViewport = (yWindow - yWinOrg) * (yViewExt / yWinExt) + yViewOrg unde (xWindow, yWindow) este punct in coordonate logice care trebuie translatat; (xViewport, yViewport) este punct in coordonate de dispozitiv; (xWinOrg, yWinOrg) = originea ferestrei in coordonate logice; (xViewOrg, yViewOrg) = originea vizorului in coordonate dispozitiv. Formulele de mai sus implica faptul ca punctul (xWinOrg, yWinOrg) este intotdeauna mapat la punctul (xViewOrg, yViewOrg). (xWinExt, yWinExt) = extensia ferestrei in coordonate logice; (xViewExt, yViewExt) = extensia vizorului in coordonate de dispozitiv; In majoritatea modurilor de mapare aceste extensii sint prestabilite si nu pot fi modificate. Raportul intre extensia vizorului si extensia ferestrei reprezinta un factor de scalare folosit pentru convertirea unitatilor logice in unitati de dispozitiv. Extensiile pot avea valori negative: aceasta inseamna ca nu este obligatoriu ca valorile pe axa x sa creasca spre dreapta si valorile pe axa y sa creasca in jos.

  • 6

    Functiile folosite pentru a realiza conversia intre puncte reprezentate in coordonate de dispozitiv in puncte reprezentate in coordonate logice si invers sunt:

    DPtoLP(hdc, pPoints, iNumber);

    LPtoDP(hdc, pPoints, iNumber);

    pPoints = matrice de structuri POINT iNumber = numarul de puncte care urmeaza a fi convertite. Daca dorim sa stim unde este punctul din centru in unitati MM_LOENGLISH, trebuie sa folosim DPtoLP : CRect rect;

    GetClientRect (&rect);

    CPoint point (rect.Width () / 2, rect.Height () / 2);

    CClientDC dc (this);

    dc.SetMapMode (MM_LOENGLISH);

    dc.DPtoLP (&point);

    DPtoLP va returna coordonatele punctului central in coordonate logice. Daca dorim sa stim coordonatele in pixeli al punctului de coordonate logice (100,100) in modul de mapare MM_LOENGLISH vom folosi LPtoDP: CPoint point (100, 100);

    CClientDC dc (this);

    dc.SetMapMode (MM_LOENGLISH);

    dc.LPtoDP (&point);

    Modul MM_TEXT Functiile SetViewportOrgEx si SetWindowOrgEx modifica originea vizorului si a ferestrei. Aceste functii au ca efect deplasarea axelor astfel incit punctul de coordonate (0,0) nu se mai refera la coltul din stanga sus al ecranului. In general se foloseste doar una din cele doua functii. Explicati asupra lucrului cu aceste functii:

    daca schimbam originea vizorului la (xViewOrg, yViewOrg) atunci punctul logic de coordonate (0,0) va fi mapat la punctul de coordonate de dispozitiv (xViewOrg, yViewOrg).

    daca schimbam originea ferestrei la (xWinOrg, yWinOrg) atunci acest punct logic va fi mapat la punctul de coordonate de dispozitiv (0,0) care este intotdeauna coltul din stinga sus al zonei client.

    Exemplu Mutare origine

  • 7

    Sa presupunem ca zona client are latimea cxClient si inaltimea cyClient. Daca dorim ca punctul de coordonate logice (0,0) sa se afle in centrul zonei client, atunci: SetViewportOrgEx(hdc, cxClient/2, cyClient/2, NULL);

    Valorile logice ale axei x sint cuprinse in intervalul [-cxClient/2, cxClient/2], iar

    cele ale axei y in intervalul [-cyClient/2, cyClient/2]. Afisarea de text incepind cu coltul din stanga sus, care are coordonatele de dispozitiv (0,0) inseamna folosirea urmatoarelor coordonate logice:

    TextOut(hdc, -cxClient/2, -cyClient/2, ...,...);

    Acelasi rezultat poate fi obtinut si cu functia SetWindowOrgEx in locul

    functiei SetViewportOrgEx:

    SetWindowOrgEx(hdc, -cxClient/2, -cyClient/2, NULL);

    Setarea extent-ului O aplicatie poate modifica in mod direct extentul ferestrei sau al vizorului numai daca modul de mapare este MM_ISOTROPIC sau MM_ANISOTROPIC. Modficarea extentului ferestrei se face cu ajutorul functiei SetWindowExt, iar extentul vizorului se modifica cu functia SetViewportExt. Valorile se dau totdeauna in unitati absolute, nu in unitati logice si nu sunt afectate de modul curent de mapare. Setarea unui extent la valoarea zero nu este permisa. Din cauza ca perechea de extent-uri stabileste un factor de scalare ce va fi folosit in conversii, marimea extentului ar trebui sa fie cat mai mica posibila pentru a simplifica calculele, de exemplu folosirea de extent-uri de 400 si 300 este echivalent cu exetent-uri de 4 si 3. Pentru a schimba orientarea unei axe (fata de orientarea implicita data de Windows), factorul de scalare trebuie sa fie negativ. Urmatorul cod are ca efect schimbarea orientarii axei y, y

    pozitiv va fi in sus.

    SetMapMode(hDC, MM_ANISOTROPIC);

    SetViewportExt(hDC, 1, -1);

    SetWindowExt(hDC, 1, 1);

  • 8

    Setarea originilor

    Functiile folosite sunt: SetWindowOrg, OffsetWindowOrg, SetViewportOrg si OffsetViewportOrg. Originile sunt independente de extent. Originile sunt specificate in unitati absolute ce nu sunt afectate de modul curent de mapare.

    Exemple Setam un mod de mapare in care la o unitate logica ii corespund trei unitati de dispozitiv:

    SetMapMode(hDC, MM_ANISOTROPIC);

    SetWindowOrg(hDC, 0, 0);

    SetWindowExt(hDC, 1, 1);

    SetViewportOrg(hDC, 0, 0);

    SetViewportExt(hDC, 3, 3); Urmatorul cod deseneaza un dreptunghi de 1 pe 2 mm.

    SetMapMode(hDC, MM_HIMETRIC);

    SetViewportOrg(hDC, 0, 100); // Ce ...?

    SetWindowOrg(hDC, 0, 0);

    Rectangle(hDC, 0, 0, 100, 200); Unitatile de dispozitiv sunt mapate la rezolutia dispozitivului fizic:

    SetMapMode(hDC, MM_ANISOTROPIC);

    SetWindowOrg(hDC, 0, 0);

    SetWindowExt(hDC, 600, 600); // logical window is 600 dpi

    SetViewportOrg(hDC, 0, 0);

    // Device viewport is dpi of actual output device.

    SetViewportExt(hDC, GetDeviceCaps(hDC, LOGPIXELSX),

    GetDeviceCaps(hDC, LOGPIXELSY));

  • 9

    Obtinerea informatiilor despre un periferic Functia CDC::GetDeviceCaps Urmatorul cod obtine rezolutia ecranului, in pixeli: CClientDC dc (this);

    int cx = dc.GetDeviceCaps (HORZRES);

    int cy = dc.GetDeviceCaps (VERTRES);

    Functia GetDeviceCaps va returna totdeauna valori fizice corecte pentru imprimanta sau orice alt periferic hardcopy (de exemplu LOGPIXELSX si LOGPIXELSY). Pentru o imprimanta laser cu 600 dpi, LOGPIXELSX si LOGPIXELSY vor avea valoarea 600. Useful GetDeviceCaps Parameters

    Parameter Returns HORZRES Width of the display surface in pixels VERTRES Height of the display surface in pixels HORZSIZE Width of the display surface in millimeters VERTSIZE Height of the display surface in millimeters LOGPIXELSX Number of pixels per logical inch horizontally LOGPIXELSY Number of pixels per logical inch vertically NUMCOLORS For a display device, the number of static colors; for a printer or

    plotter, the number of colors supported BITSPIXEL Number of bits per pixel PLANES Number of bit planes RASTERCAPS Bit flags detailing certain characteristics of the device, such as

    whether it is palettized and whether it can display bitmapped images TECHNOLOGY Bit flags identifying the device typescreen, printer, plotter, and so

    on

  • 10

    Desenarea pe ecran (Exemple de cod)

    Windows este un SO independent de dispozitiv. Pentru c nu tim niciodat dinainte ce tipuri de periferice pot fi conectate la sistemul utilizatorului, nu putem face presupuneri despre posibilitile de afiare ale acestora. Funciile care deseneaz pe ecran, trebuie s fac acest lucru indirect prin intermediul aa numitelor contexte de dispozitiv (DC). Windows manipuleaz perifericele cu ajutorul driver-elor instalate de utilizator pe sistem. Aceste drivere intercepteaz datele pe care aplicaiile doresc s le afieze i apoi translateaz aceste date pentru perifericul respectiv pentru a fi reprezentate ct mai corect. Driverele de dispozitiv trebuie s ia cerinele de afiare s le ajusteze (fine tuning) funcie de perifericul (dispozitivul) pe care vor aprea. Exist o structur de date, cunoscut sub numele de context de dispozitiv, care leag aplicaia de driverul dispozitivului. Un context de dispozitiv este mai mult dect o structur de date n memorie care pstreaz atributele suprafeei de desenare a ferestrei. Aceste atribute includ: penia, pensula, fontul, etc. Un DC conine la un moment dat o singur peni (de exemplu). Pentru a folosi diverse penie, trebuie s le crem i apoi selectm n cadrul DC. Zona client este suprafaa n care un program poate desena orice. Afiarea n zona client se face cu ajutorul funciilor din GDI.

    Construirea unei aplicatii pentru exemplificarea folosirii penitelor, pensulelor si fonturilor

    Vom construi o aplicaie cu arhitectura Document/View i de tip SDI, n care vom exemplifica folosirea penielor, fonturilor i a pensoanelor. Vom afia text cu diverse fonturi, vom desena linii de diferite grosimi (cu penie diferite), vom desena dreptunghiuri sau zone nchise umplute cu pensule diferite.

    WM_PAINT Un mesaj important pe care fiecare program Windows, cu o fereastr, trebuie s-l trateze este WM_PAINT. Windows trimite mesajul WM_PAINT ferestrei aplicaiei cnd fereastra trebuie s se redeseneze. Mai multe evenimente fac ca Windows s trimit acest mesaj: Cnd utilizatorul lanseaz programul n execuie pentru prima dat, fereastra

    aplicaiei primete acest mesaj imediat dup nceperea execuiei, pentru a afia informaiile necesare pentru nceput.

  • 11

    Cnd fereastra a fost redimensionat sau a fost descoperit (total sau parial) de o alt fereastr. Partea din fereastr care a fost acoperit trebuie acum redesenat i actualizat.

    Cnd un program i trimite indirect mesajul WM_PAINT prin invalidarea zonei client. Aceast funcionalitate asigur faptul c o aplicaie poate schimba coninutul ferestrei aproape n orice moment dorete. De exemplu, un procesor de texte poate invalida fereastra sa dup ce utilizatorul a copiat tet din Clipboard.

    Macroul din harta de mesaje pentru WM_PAINT este ON_WM_PAINT(), iar funcia ce corespunde tratrii acestui mesaj este OnPaint(). Posibil cod n OnPaint():

    void CView::OnPaint()

    {

    // rutina standard de desenare

    CPaintDC dc(this);

    OnPrepareDC(&dc);

    OnDraw(&dc);

    }

    CPaintDC este o clas special pentru gestionarea DC-ului folosit numai cnd se rspunde la mesajul WM_PAINT. Un obiect al clasei CPaintDC n afar de faptul c creaz DC apeleaz i funcia BeginPaint() n constructorul clasei i apeleaz funcia EndPaint() n destructor. Constructorul CPaintDC ia un singur argument, care este un pointer la fereastra pentru care am creat DC. Pointer-ul this puncteaz la vederea curent, deci putem s-l pasm n constructor pentru a crea un DC pentru vederea curent. OnPrepareDC() este o funcie din CView care pregtete DC-ul pentru a fi folosit. OnDraw() afieaz documentul n zona client.

    Schimbarea afisarii

    Logica aplicaiei este urmtoarea: la apsarea butonului stng al mouse-ului se va afia fie text cu un anumit font, fie o linie cu o anumit peni, fie un dreptunghi umplut cu o anumita pensula. Comutarea afirii se face cu ajutorul unei variabile m_Display definit n clasa derivat din CView. Valoarea implicit a acestei variabile este Fonts i se actualizeaz circular pe mesajul WM_LBUTTONDOWN, cu valorile Pens i apoi Brushes, samd. n definiia clasei: protected:

    enum {Fonts, Pens, Brushes} m_Display;

  • 12

    n constructor:

    m_Display = Fonts; iar desenarea in void CXView::OnDraw(CDC* pDC)

    {

    CPaint1Doc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    switch (m_Display)

    {

    case Fonts:

    ShowFonts(pDC);

    break;

    case Pens:

    ShowPens(pDC);

    break;

    case Brushes:

    ShowBrushes(pDC);

    break;

    }

    }

    Vom scrie funciile ShowFonts(), ShowPens() i ShowBrushes(). Vom aduga funciile n definiia clasei i apoi vom scrie codul n implementarea clasei. void CXView::OnLButtonDown(UINT nFlags, CPoint point)

    {

    if (m_Display == Fonts)

    m_Display = Pens;

    else if (m_Display == Pens)

    m_Display = Brushes;

    else

    m_Display = Fonts

    Invalidate(); // genereaz mesajul WM_PAINT

    CView::OnLButtonDown(nFlags, point);

    }

    Folosirea fonturilor

    Trebuiesc cercetate fonturile care sunt instalate n sistem. Un font Windows este descris ntr-o structur LOGFONT.

  • 13

    LOGFONT Fields and Their Descriptions

    Field Description lfHeight Font height in logical units lfWidth Font width in logical units lfEscapement Angle at which to draw the text lfOrientation Character tilt in tenths of a degree lfWeight Font weight lfItalic A nonzero value indicates italics lfUnderline A nonzero value indicates an underlined font lfStrikeOut A nonzero value indicates a strikethrough font lfCharSet Font character set lfOutPrecision How to match requested font to actual font lfClipPrecision How to clip characters that run over clip area lfQuality Print quality of the font lfPitchAndFamily Pitch and font family lfFaceName Typeface name Unitatea logic (logical units) depinde de modul de mapare folosit. Modul de mapare implicit este MM_TEXT care nseamn c o unitate logic este egal cu un pixel.

    Moduri de mapare

    Mode Unit MM_HIENGLISH 0.001 inch

    MM_HIMETRIC 0.01 millimeter

    MM_ISOTROPIC Arbitrary MM_LOENGLISH 0.01 inch

    MM_LOMETRIC 0.1 millimeter MM_TEXT Device pixel

    MM_TWIPS 1/1440 inch

    Escapement se refer la a scrie text de-a lungul unei linii ce face cu orizontala un anumit unghi. Orientation se refer la a scrie text de-a lungul unei linii (flat line). Ponderea (weight) fontului se refer la (thickness) subirimea literelor. Au fost definite un numr de constante pentru a fi utilizate cu acest cmp: FW_DONTCARE, FW_THIN, FW_EXTRALIGHT, FW_ULTRALIGHT, FW_LIGHT, FW_NORMAL, FW_REGULAR, FW_MEDIUM, FW_SEMIBOLD, FW_DEMIBOLD, FW_BOLD, FW_EXTRABOLD, FW_ULTRABOLD, FW_BLACK, i FW_HEAVY. Nu toate fonturile sunt disponibile n toate ponderile. Sunt disponibile patru mulimi de caractere (ANSI_CHARSET, OEM_CHARSET, SYMBOL_CHARSET, i UNICODE_CHARSET), dar pentru a scrie text n englez vom folosi totdeauna ANSI_CHARSET.

  • 14

    Ultimul cmp din structur reprezint numele fontului (de ex. Helvetica, Times New Roman, etc.) void CXView::ShowFonts(CDC * pDC)

    {

    // Initializare structura LOGFONT pentru fonturi

    LOGFONT logFont;

    logFont.lfHeight = 8;

    logFont.lfWidth = 0;

    logFont.lfEscapement = 0;

    logFont.lfOrientation = 0;

    logFont.lfWeight = FW_NORMAL;

    logFont.lfItalic = 0;

    logFont.lfUnderline = 0;

    logFont.lfStrikeOut = 0;

    logFont.lfCharSet = ANSI_CHARSET;

    logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;

    logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;

    logFont.lfQuality = PROOF_QUALITY;

    logFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;

    strcpy(logFont.lfFaceName, "Times New Roman");

    // Initializare pozitie text in fereastra.

    UINT position = 0;

    // Creaza si afiseaza 8 exemple de fonturi.

    for (UINT x=0; xSelectObject(&font);

    // Tiparim textul cu noul font.

    position += logFont.lfHeight;

    pDC->TextOut(20, position, "Exemplu de font.");

    // Restauram vechiul font in DC.

    pDC->SelectObject(oldFont);

    }

  • 15

    }

    Explicaii la acest cod. Se va rula aplicaia n acest moment. Se va constata c nu pot fi afiate toate informaiile n zona client.

    Marire si pozitionare fereastra

    Informaiile nu pot fi afiate n zona client la o rezolutie a ecranului de 800*600. Acest lucru se corecteaz prin mrirea ferestrei, care se face n funcia PreCreateWindow() din CMainFrame. Aceast funcie este apelat nainte ca fereastra s fie creat. PreCreateWindow() are un singur parametru, o referin la o structur CREATESTRUCT. Aceast structur conine informaii despre fereastra care va fi creat.

    CREATESTRUCT Structure

    typedef struct tagCREATESTRUCT {

    LPVOID lpCreateParams;

    HANDLE hInstance;

    HMENU hMenu;

    HWND hwndParent;

    int cy;

    int cx;

    int y;

    int x;

    LONG style;

    LPCSTR lpszName;

    LPCSTR lpszClass;

    DWORD dwExStyle;

    } CREATESTRUCT;

    cx i cy menin limea i nlimea ferestrei, iar x i y poziia acesteia. Se inhib redimensionarea ferestrei (style). BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

    {

    cs.cx = 440;

    cs.cy = 480;

    cs.style &= ~WS_SIZEBOX;

    if( !CFrameWnd::PreCreateWindow(cs) )

    return FALSE;

    return TRUE;

    }

    Majoritatea funciilor rescrise i apelate de cadrul de lucru trebuie s apeleze n final versiunea din clasa de baz.

  • 16

    Folosirea penitelor

    Vezi clasa CPen.

    void CXView::ShowPens(CDC * pDC)

    {

    // Initializam pozitia liniei

    UINT position = 10;

    // Desenam 16 linii in fereastra

    for (UINT x=0; xSelectObject(&pen);

    // Desenam o linie cu noua penita

    position += x * 2 + 10;

    pDC->MoveTo(20, position);

    pDC->LineTo(400, position);

    // Repunem vechea penita in DC

    pDC->SelectObject(oldPen);

    }

    } Explicaii la acest cod.

    Stiluri penita

    Style Description PS_DASH A pen that draws dashed lines PS_DASHDOT A pen that draws dash-dot patterned lines PS_DASHDOTDOT A pen that draws dash-dot-dot patterned lines PS_DOT A pen that draws dotted lines

    PS_INSIDEFRAME A pen that's used with shapes, in which the line's thickness must not extend outside the shape's frame

    PS_NULL A pen that draws invisible lines PS_SOLID A pen that draws solid lines

    Folosirea pensulelor

    Cu ajutorul unei pensule desenam interiorul unei figuri de pe ecra. Putem crea pensule solide, pensule cu un anumit ablon i chiar pensule din bitmap-uri.

  • 17

    void CXView::ShowBrushes(CDC * pDC)

    // Initializam dreptunghiul de pozitionare

    UINT position = 0;

    // Selectam penita ce va fi folosita pentru

    // a desena conturul dreptunghiului

    CPen pen(PS_SOLID, 5, RGB(255, 0, 0));

    CPen* oldPen = pDC->SelectObject(&pen);

    // Desenam 7 dreptunghiuri.

    for (UINT x=0; xSelectObject(brush);

    // Desenam dreptunghiul

    position += 50;

    pDC->Rectangle(20, position, 400, position + 40);

    // Restauram vechea pensula si o stergem pe cea

    noua

    pDC->SelectObject(oldBrush);

    delete brush;

    }

    // Restauram vechea penita

    pDC->SelectObject(oldPen);

    } Stiluri pentru pensoane:

    HS_HORIZONTAL--Horizontal

    HS_VERTICAL--Vertical

    HS_CROSS--Horizontal and vertical

    HS_FDIAGONAL--Forward diagonal

    HS_BDIAGONAL--Backward diagonal

  • 18

    HS_DIAGCROSS--Diagonal in both directions

    Observaie: Trebuie s apelm Invalidate() n OnLButtonDown(). Invalidate() are un singur argument (Boolean) cu valoarea implicit TRUE. Acest argument are ca efect tergerea sau nu a background-ului. Dac valoarea este FALSE, backgroundul nu va fi ters.

    Ferestre cu bare de navigare

    (scrolling Windows ferestre cu derulare) Ferestrele ne permit de a partiiona ecranul ntre diverse aplicaii i documente. Dac folosim MFC i derivm clasa de vizualizare din CScrollView, atunci fereastra are posibiliti de derulare.

    Indicatii de construire a unei aplicatii cu ferestre cu

    derulare Vom construi o aplicaie pentru a exemplifica posibilitile de derulare. n cadrul aplicaiei iniial se vor afia 5 linii de text, iar pe mesajul WM_LBUTTONDOWN vom aduga de fiecare dat nc 5 linii te text, astfel c la un moment dat textul nu va mai ncpea n fereastr. Numrul liniilor de text care sunt afiate n zona client le vom gestiona cu ajutorul unei variabile din clasa derivata din CDocument public:

    int m_NumLines; pe care o iniializm n constructorul clasei:

    m_NumLines = 5; Aceast variabil o putem serializa: void CScrollDoc::Serialize(CArchive& ar)

    {

    if (ar.IsStoring())

    {

    ar > m_NumLines;

    }

    }

  • 19

    n vizualizare: void CMyScrollView::OnDraw(CDC* pDC)

    {

    CScrollDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    // obtinem numarul de linii din document

    int numLines = pDoc->m_NumLines;

    // Initializam o structura LOGFONT pentru fonturi.

    LOGFONT logFont;

    logFont.lfHeight = 24;

    logFont.lfWidth = 0;

    logFont.lfEscapement = 0;

    logFont.lfOrientation = 0;

    logFont.lfWeight = FW_NORMAL;

    logFont.lfItalic = 0;

    logFont.lfUnderline = 0;

    logFont.lfStrikeOut = 0;

    logFont.lfCharSet = ANSI_CHARSET;

    logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;

    logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;

    logFont.lfQuality = PROOF_QUALITY;

    logFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;

    strcpy(logFont.lfFaceName, "Times New Roman");

    // Cream un nou font si il selectam in DC

    CFont* font = new CFont();

    font->CreateFontIndirect(&logFont);

    CFont* oldFont = pDC->SelectObject(font);

    // Initializam pozitia textului in fereastra

    UINT position = 0;

    // Cream si afisam 8 linii de text

    for (int x=0; xTextOut(20, position, s);

    // Trecem pe linia urmatoare

    position += logFont.lfHeight;

    }

    // Restauram vechiul font in DC si stergem fontul creat de program

    pDC->SelectObject(oldFont);

    delete font;

    }

  • 20

    Explicaie cod. Se va rula aplicaia.

    Modificarea codului pentru a creste numarul de linii afisate pe ecran

    Pe mesajul WM_LBUTTONDOWN

    void CMyScrollView::OnLButtonDown(UINT nFlags, CPoint

    point)

    {

    CScrollDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    // Marim numarul liniilor de afisat

    //(cu 5 la fiecare clic stanga mouse)

    pDoc->m_NumLines += 5;

    // Redesenam fereastra

    Invalidate();

    CScrollView::OnLButtonDown(nFlags, point);

    }

    Micsorarea numarului de linii

    void CMyScrollView::OnRButtonDown(UINT nFlags, CPoint point)

    {

    CScrollDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    // Micsoram numarul liniilor de afisat

    // (cu 5 la fiecare clic dreapa mouse)

    pDoc->m_NumLines -= 5;

    if (pDoc->m_NumLines < 0)

    {

    pDoc->m_NumLines = 0;

    }

    // Redesenam fereastra.

    Invalidate();

    CScrollView::OnRButtonDown(nFlags, point);

    }

    Dac rulm aplicaia vom observa c barele de derulare nu apar. Trebuie modificat funcia OnDraw().

    Linii de cod ce se vor adauga la OnDraw()

    // Calculam marimea documentului

    CSize docSize(100, numLines*logFont.lfHeight);

    // Calculam marimea paginii

    CRect rect;

    GetClientRect(&rect);

    CSize pageSize(rect.right, rect.bottom);

  • 21

    // Calculam marimea liniei

    CSize lineSize(0, logFont.lfHeight);

    // Ajustam barele de navigare

    SetScrollSizes(MM_TEXT, docSize, pageSize, lineSize);