Iczelion - 05 - Mehr über Text

Tutorial 5: Mehr über Text



Wir werden noch mehr mit Textattributen herum experimentieren, z.B. Schriftarten und Farben.

Laden Sie hier das Beispiel herunter.

Theorie:

Windows Farbensystem basiert auf den RGB-Werten, R=Rot, G=Grün, B=Blau. Wenn Sie in Windows eine Farbe definieren wollen, müssen Sie die gewünschte Farbe anhand dieser drei Grundfarben zusammensetzen. Jede Farbe hat einen Wert zwischen 0 und 255 (ein Byte Wert). Wenn Sie zum Beispiel pures Rot haben wollen, müssen Sie 255,0,0 benutzen. Oder wenn Sie pures Weiss haben wollen, müssen Sie 255,255,255 benutzen. Wie Sie anhand der Beispiele sehen können, ist es sehr schwierig, die gewünschte Farbe zu bekommen, die Sie benötigen, da Sie ein gutes Verständnis fürs mischen der passenden Farben haben müssen.

Für Textfarbe und Hintergrund können Sie SetTextColor und SetBkColor benutzen. Beide benötigen ein Handle des Device Context und einen 32-bit RGB Wert. Die Struktur der 32-bit RGB Werte ist wie folgt definiert:

RGB_value struct unbenutzt db 0 blau db ? grün db ? rot db ? RGB_value ends


Beachten Sie, dass das erste Byte nicht benutzt wird und gleich Null sein sollte. Die Reihenfolge der übrigen drei Bytes ist umgekehrt, Blau, Grün, Rot. Wie dem auch sei, wir werden diese Struktur nicht benutzen, da sie lästig zu initialisieren und zu benutzen ist. Statt dessen werden wir eine Makro erstellen. Dem Makro werden folgende drei Parameter übergeben: Rot-, Grün- und Blauwerte. Es wird den gewünschten 32-bit RGB Wert erzeugen und in EAX speichern. Das Makro sieht wie folgt aus:

RGB macro red,green,blue xor eax,eax mov ah,blue shl eax,8 mov ah,green mov al,red endm


Sie können das Makro in die Include-Datei einfügen, für späteren Gebrauch.

Sie können einen Font (Schriftart) "kreieren" indem Sie CreateFont oder CreateFontIndirect aufrufen. Der Unterschied zwischen den beiden Funktionen ist, dass CreateFontIndirect nur ein Parameter übergeben wird: einen Zeiger auf eine logische Font Struktur, LOGFONT. CreateFontIndirect ist der flexiblere Weg der beiden, insbesondere, wenn ihr Programm den Font öfters ändern muss.

Wie dem auch sei werden wir in unserem Beispiel nur ein Font zur Demonstration "kreieren", so dass wir mit CreateFont auskommen. Nach dem Aufruf von CreateFont, wird ein Handle auf den Font welchen Sie im Device Context auswählen müssen. Danach wird jede Text-API-Funktion den im Device Context ausgewählten Font benutzen.

Inhalt:

.386 .model flat,stdcall option casemap:none WinMain proto :DWORD,:DWORD,:DWORD,:DWORD include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\gdi32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\gdi32.lib RGB macro red,green,blue xor eax,eax mov ah,blue shl eax,8 mov ah,green mov al,red endm .data ClassName db "SimpleWinClass",0 AppName db "Our First Window",0 TestString db "Win32 Assembler ist grossartig und einfach!",0 FontName db "script",0 .data? hInstance HINSTANCE ? CommandLine LPSTR ? .code start: invoke GetModuleHandle, NULL mov hInstance,eax invoke GetCommandLine mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT invoke ExitProcess,eax WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL wc:WNDCLASSEX LOCAL msg:MSG LOCAL hwnd:HWND mov wc.cbSize,SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra,NULL mov wc.cbWndExtra,NULL push hInst pop wc.hInstance mov wc.hbrBackground,COLOR_WINDOW+1 mov wc.lpszMenuName,NULL mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax invoke RegisterClassEx, addr wc invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInst,NULL mov hwnd,eax invoke ShowWindow, hwnd,SW_SHOWNORMAL invoke UpdateWindow, hwnd .WHILE TRUE invoke GetMessage, ADDR msg,NULL,0,0 .BREAK .IF (!eax) invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .ENDW mov eax,msg.wParam ret WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM LOCAL hdc:HDC LOCAL ps:PAINTSTRUCT LOCAL hfont:HFONT .IF uMsg==WM_DESTROY invoke PostQuitMessage,NULL .ELSEIF uMsg==WM_PAINT invoke BeginPaint,hWnd, ADDR ps mov hdc,eax invoke CreateFont,24,16,0,0,400,0,0,0,OEM_CHARSET,\ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\ DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\ ADDR FontName invoke SelectObject, hdc, eax mov hfont,eax RGB 200,200,50 invoke SetTextColor,hdc,eax RGB 0,0,255 invoke SetBkColor,hdc,eax invoke TextOut,hdc,0,0,ADDR TestString,SIZEOF TestString invoke SelectObject,hdc, hfont invoke EndPaint,hWnd, ADDR ps .ELSE invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret .ENDIF xor eax,eax ret WndProc endp end start

Analyse:

invoke CreateFont,24,16,0,0,400,0,0,0,OEM_CHARSET,\ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\ DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\ ADDR FontName


CreateFont erzeugt einen logischen Font, der den angegebenen Parametern am nächsten kommt und auch verfügbar ist. Diese Funktion hat mehr Parameter als jede andere Funktion in Windows. Sie gibt einen Handle auf den logischen Font zurück, welcher von der SelectObject Funktion gebraucht wird. Wir werden uns die Parameter im Detail anschauen.

CreateFont proto nHeight:DWORD,\ nWidth:DWORD,\ nEscapement:DWORD,\ nOrientation:DWORD,\ nWeight:DWORD,\ cItalic:DWORD,\ cUnderline:DWORD,\ cStrikeOut:DWORD,\ cCharSet:DWORD,\ cOutputPrecision:DWORD,\ cClipPrecision:DWORD,\ cQuality:DWORD,\ cPitchAndFamily:DWORD,\ lpFacename:DWORD


nHeight   Die gewünschte Höhe der Buchstaben. 0 bedeutet Standardgröße.
nWidth   Die gewünschte Breite der Buchstaben. Normalerweise sollte dieser Wert 0 sein, was Windows erlaubt, die Breite an die Höhe anzupassen. Wie dem auch sei, in unserem Beispiel ist die Standardbreite der Buchstaben schwer zu lesen, weshalb ich die Breite 16 statt dessen benutze.

nEscapement   Spezifiziert die Ausrichtung des nächsten Buchstabens relativ zum vorherigen, in Zehntel Grad. Normalerweise auf 0 gesetzt. Geben Sie 900 an, um alle Buchstaben vom ersten an nach oben auszugeben, 1800 um rückwärts zu schreiben oder 2700 um jeden Buchstaben von oben nach oben auszugeben.

nOrientation   Spezifiziert um wieviel der Buchstabe rotiert werden soll, wenn die Ausgabe in Zehntel Grad statt findet. Geben Sie 900 an, um alle Buchstaben auf dem Kopf auszugeben, 1800 für eine Auf- und Ab-Ausgabe, etc.

nWeight   Setzt die Dicke der Buchstaben fest. Windows definiert folgende Größe:

FW_DONTCARE equ 0 FW_THIN equ 100 FW_EXTRALIGHT equ 200 FW_ULTRALIGHT equ 200 FW_LIGHT equ 300 FW_NORMAL equ 400 FW_REGULAR equ 400 FW_MEDIUM equ 500 FW_SEMIBOLD equ 600 FW_DEMIBOLD equ 600 FW_BOLD equ 700 FW_EXTRABOLD equ 800 FW_ULTRABOLD equ 800 FW_HEAVY equ 900 FW_BLACK equ 900
cItalic   0 für normal, jeden anderen Wert für kursive Buchstaben.
cUnderline   0 für normal, jeden anderen Wert für unterstrichene Buchstaben.
cStrikeOut   0 für normal, jeden anderen Wert für durchgestrichene Buchstaben.
cCharSet  Der Buchstabensatz des Fonts. Normalerweise OEM_CHARSET, was Windows erlaubt einen Betriebssystem abhängigen Font zu wählen.
cOutputPrecision  Spezifiziert wie dicht der ausgewählte Font an den Vorgaben sein muss, die wir wollen. Sollte normalerweise OUT_DEFAULT_PRECIS sein, was das Standard-Font-Auswahl-Verhalten definiert.
cClipPrecision  Spezifiziert die 'Abschneide'-Genauigkeit. Die 'Abschneide'-Genauigkeit definiert wie ein Buchstabe abgeschnitten wird, wenn er teilweise außerhalb der 'Abschneide'-Region liegt. Sie sollten mit CLIP_DEFAULT_PRECIS auskommen, was das Standard-'Abschneide'-Verhalten definiert.
cQuality  Spezifiziert die Ausgabequalität. Die Ausgabequalität definiert wie genau das GDI versucht, den Attributen des logischen Font, denen des aktuellen physischen Font nahe zu kommen. Es gibt drei zur Auswahl: DEFAULT_QUALITY, PROOF_QUALITY und  DRAFT_QUALITY.

cPitchAndFamily  Spezifiziert Neigung und Familie des Fonts. Sie müssen beides mit dem 'oder'-Operator verbinden.

lpFacename  Ein Zeiger auf einen Nullterminierten String, der die Schriftart des Fonts spezifiziert.

Die obige Beschreibung ist mehr als kurz. Sie sollten ihre Win32 API-Referenz für mehr Details zu Rate ziehen.

invoke SelectObject, hdc, eax mov hfont,eax


Nachdem wir das Handle auf den logischen Font erhalten haben, müssen wir es benutzen, um den Font in dem Device Context auszuwählen, indem wir SelectObject aufrufen. SelectObject fügt die neuen GDI Objekte wie Pens, Brushs und Fonts in den Device Context ein, die von GDI-Funktionen benutzt werden. Sie liefert ein Handle des ersetzten Objekts zurück, welches wir für weitere SelectObjekt Aufrufe sichern sollten. Nach dem SelectObject-Aufruf wird jede Textausgabe-Funktion den Font benutzen, den wir für den Device Context ausgewählt haben.

RGB 200,200,50 invoke SetTextColor,hdc,eax RGB 0,0,255 invoke SetBkColor,hdc,eax


Benutzen Sie das RGB Makro um einen 32-bit RGB Wert zu erzeugen, der von SetColorText und SetBkColor benutzt wird.

invoke TextOut,hdc,0,0,ADDR TestString,SIZEOF TestString


Rufen Sie die TextOut Funktion auf, um den Text in der Client Area auszugeben. Der Text wird in der Font-Art und Farbe erscheinen, die Sie vorher ausgewählt haben.

invoke SelectObject,hdc, hfont


Wenn wir mit dem Font fertig sind, sollten wir den alten Font im Device Context wiederherstellen. Sie sollten immer das Objekt wiederherstellen, dass Sie im Device Context ersetzt haben.


Deutsche Übersetzung: Joachim Rohde
Die original Win32Asm-Tutorials stammen von Iczelion's Win32 Assembly HomePage