Wypisywanie tekstu jest najstarszą operacją graficzną. Każda biblioteka graficzna musi obsługiwać takie podstawowe czynności. GDI w tej dziedzinie nie ustępuje, wręcz przeciwnie, wypisywnaie tekstu to zaawansowana procedura.

Czcionki

Co to jest czcionka chyba każdy wie. W GDI czcionka to kolejny obiekt, uchwyt do czcionki to HFONT.

Funkcja, która służy do tworzenia czcionek to CreateFont(), jedna z najdłuższych funkcji w WinAPI, więc już samo to ukazuje, jak zaawansowana jest praca z tekstem w GDI.

HFONT CreateFont(INT nHeight,INT nWidth,INT nEscapement,INT nOrientation,INT fnWeight,DWORD fdwItalic,
DWORD fdwUnderline,DWORD fdwStrikeOut,DWORD fdwCharSet,DWORD fdwOutputPrecision,DWORD fdwClipPrecision,
DWORD fdwQuality,DWORD fdwPitchAndFamily,LPCTSTR lpszFace);

INT nHeight
Wysokość czcionki.

INT nWidth
Średnia szerokość znaku czcionki, jeżeli podamy 0, system sam wybierze najodpowiedniejszą wartość.

INT nEscapement
Kąt nachylenia tekstu wypisanego tą czcionką(podama wartość/10=wartość w kątach).

INT nOrientation
Kąt nachylenia każdego ze znaków. Tutaj także używamy miary wartość 10=1 stopień.

INT fnWeight
Stopień pogrubienia tekstu, najczęstsze wartości:
FW_DONTCARE - 0 (system sam ustala)
FW_THIN - 100 (cieniutka)
FW_EXTRALIGHT, FW_ULTRALIGHT - 200 (ultra/ekstra cienka)
FW_LIGHT - 300 ("lekka")
FW_NORMAL, FW_REGULAR - 400 (normalna, regularna)
FW_MEDIUM - 500 (średnia)
FW_SEMIBOLD, FW_DEMIBOLD - 600 (pogrubiona)
FW_BOLD - 700 (gruba)
FW_EXTRABOLD, FW_ULTRABOLD - 800 (ultra/ekstra gruba)
FW_HEAVY, FW_BLACK - 900 (mocna/cimna)

DWORD fdwItalic
Określa czy czcionka ma być "kursywą", jeżeli tak podajemy 1, jeżeli nie 0.

DWORD fdwUnderline
Określa czy czcionka ma być podkreślona, dla tak 1, dla nie 0.

DWORD fdwStrikeOut
Określa czy czcionka ma być przekreślona, dla tak 1, dla nie 0.

DWORD fdwCharSet
Określa system kodowania znaków w czcionce, dla polskich znaków wybieramy system "Europa Środkowa", kodowo EASTEUROPE_CHARSET, a oto kilka innych przykładów:
ANSI_CHARSET - system kodowania ANSI (Amerykański)
CHINESEBIG5_CHARSET - chiński system kodowania
DEFAULT_CHARSET - domyślny system kodowania znaków, niestety nie będzie to polski, nawet gdy mamy ustawiony polski w systemie
EASTEUROPE_CHARSET - nasz środkowo-europejski system kodowania(polskie znaki)
GREEK_CHARSET - grecki system kodowania
RUSSIAN_CHARSET - rosyjski system kodowania
SYMBOL_CHARSET - system symboli

DWORD fdwOutputPrecision
Ten paramert określa precyzję znaków na wyjściu. Zwykle wybieramy tu wartość OUT_DEFAULT_PRECIS, jako domyślną precyzję.

DWORD fdwClipPrecision
Ten parametr wyznacza precyzję przycinania znaków, najlepiej użyć domyślnej wartości CLIP_DEFAULT_PRECIS

DWORD fdwQuality
Tutaj określa się jakość czcionki:
ANTIALIASED_QUALITY - korzystamy z wygładzania czcionki
DEFAULT_QUALIT - domyślna jakość czcionki
DRAFT_QUALITY - ścisłe dopasowanie się do podanych wcześniej parametrów
PROOF_QUALITY - w przypadku podania wcześniejszych parametrów, które by spowodowały nieczytelność tekstu, system może zignorować te parametry, poprawiając jakość tekstu.

DWORD fdwPitchAndFamily
W parametrze tym łączymy dwie informacje operatorem sumy bitowej. Pierwszą z nich jest rodzaj odstępu pomiędzy znakami:
DEFAULT_PITCH - wartość, która jest najsłuszniejsza, wybieramy domyślną opcję, wtedy system sam określi rodzaj czcionki
FIXED_PITCH - określamy, że w czcionce jest stała odległość pomiędzy znakami, tak jak np. w czcionce Courier New
VARIABLE_PITCH - określamy, że w czcionce są znaki, których grubość zależy od danego znaku, jak już wspomniałem należy wybrać tu wartość domyślną, wtedy system sam sobie ustali jaki to rodzaj czcinki.
Drugą informacją w tym parametrze jest rodzinca czcionek, tutaj także nie musimy okreslać z jakiej rodzin korzystamy, podając FF_DONTCARE GDI samo ustali z jakiej rodziny korzystamy.

LPCTSTR lpszFace
Ostatni parametr jest najważniejszy, tutaj podajemy nazwę czcionki, z jakiej ma zostać utworzony obiekt czcionki, możemy tutaj podać np. "Times New Roman" lub "Arial". Podanie 0 lub wpisanie nie istniejącej nazwy spowoduje, że system dopasuje sobie czcionkę, która będzie najbardziej pasowała do podanych wcześniej parametrów.

Po utworzeniu obiektu czcionki należy go umieścić w kontekście urządzenia, w którym chcemy wypisywać tekst. Sposób postępownaia jest tutaj jak z każdym innym obiektem kontekstu, używamy funkcji SelectObject() i nie możemy zapomnieć o zwolnieniu obiektu czcionki, który podmieniamy.

Atrybuty tekstu

Zanim jeszcze poznamy funkcje wypisujące tekst, chcę przypomnieć, że w kontekście urządzenia, są atrybuty tekstu, które już poznaliśmy:
- kolor tekstu
- tryb tła tekstu
- kolor tła tekstu
- dodatkowy odstęp między znakami(oprócz tego z czcionki)
- obiekt czcionki(przed chwilą opisany)
Są one wykorzystywane przez funkcje rysjuące, dlatego warto przed operacja pisania ustawić te atrybuty w kontekście. Funkcje ustawiające je poznaliśmy już przy omawianiu kontekstów.

Bezpośrednie wypisanie tekstu

Do wypisania tekstu na ekranie służy funkcja TextOut():

BOOL TextOut(HDC hdc,INT nXStart,INT nYStart,LPCSTR lpText,INT cbText);

Jako pierwszy parametr podajemy uchwyt, dwa kolejne współrzędne punktu rysowania tekstu, kolejny to wypisywany tekst, po nim określamy długość wypisywanego tekstu.

Tutaj trzeba sobie powiedzieć o punkcie według, którego rysowany jest tekst, a może on być w rónych pozycjach, ustawia się go jako atrybut w kontekście funkcją SetTextAlign().

UNIT SetTextAlign(HDC hdc,UNIT fMode);

Jest to atrybut tekstu, którego nie opisałem podczas omawiania atrbutów kontekstu, jedynie o nim wspomniałem. Właśnie w nim definiujemy gdzie ma znajdować się punkt rysowania tekstu funkcji TextOut().

Oto możliwe opcje w poziomie:
TA_LEFT - punkt będzie skrajnie po lewej stronie tekstu(domyślnie)
TA_CENTER - punkt znajdzie się w środku tekstu
TA_RIGHT - punkt znajdzie się po prawej stronie tekstu

Opcje w pionie:
TA_TOP - punkt znajduje się w skrajnej górnej części tekstu(domyślnie)
TA_BASELINE - punkt znajduje się po środku tekstu
TA_BOTTOM - punkt znajduje sie u dołu tekstu

Zachowanie względem współrzędnych pióra:
TA_UPDATECP - parametry podane w funkcji nie są wykorzystywane, ale jako punkt rysowania wykorzystany będzie punkt położenia pióra
TA_NOUPDATECP - pozycja pióra nie jest brana pod uwagę(domyślnie)

Zaawansowane wypisanie tekstu

Pisząc zaawansowane mam na myśli funkcję, która jest troszkę bardziej złożona niż TextOut(). Jest nią DrawText():

INT DrawText(HDC hdc,LPCSTR lpText,INT cbText,LPRECT lpRect,UNIT uFormat);

Pierwsze trzy parametry odpowiadają parametrom z TextOut, są to kolejno kontekst, tekst i długość tekstu. Czwarty paramert wygląda chyba znajomo? Jest to struktura wykorzystywana do definiowania prostokąta, przypomnij sobie jej budowę(rysowanie prostokąta), w tej strukturze określamy wymiary prostokąta w którym zostanie wypisany tekst. Jak widzisz funkcja ta do definiowania miejsca rysowania tekstu używa prostokątnego pola.

Parametr uFormat określa jak w tym prostokacie zostanie umieszczony napis:
Wyrównania w poziomie:
DT_CENTER - tekst zostanie narysowany w poziomej środkowej części prostokąta
DT_LEFT - tekst zostanie narysowany po lewej stronie prostokata(domyślnie)
DT_RIGHT - tekst zostanie narysowany po prawej stronie prostokata
Wyrównania w pionie:
DT_TOP - tekst zostanie narysowany w górnej części prostokąta(domyślnie)
DT_SINGLELINE - aby, móc użyć innego pionowego stylu niż DT_TOP trzeba zdefiniować także tą flagę, wtedy informujemy, że napis będize w jednej linni
DT_VCENTER - tekst zostanie narysowany w pionowej środkowej części prostokąta
DT_BOTTOM - tekst zostanie narysowany w dolnej części prostokąta

To nie jest koniec przewagi DrawText(), funkcja ta potrafi wyświetlać tekst w wielu linniach(pod warunkiem, że nie zdefiniowana jest flaga DT_SINGLELINE). Aby tekst przeskoczył do następnej linni, w ciągu wypisywanych znaków funkcja musi napotkać dwa znaki specjalne, następujące po sobie: "\r\n".