Wyjście Spis treści Poprzedni Następny
Autor:
©Iczelion |
©2008 mgr
Jerzy Wałaszek |
|
Poeksperymentujemy z atrybutami tekstu, tj. z czcionką i kolorem.
Załaduj sobie plik źródłowy tego przykładu {z tego archiwum}.
System kolorów w Windows oparty jest na wartościach RGB, R=czerwony (red), G=zielony (green), B=niebieski (blue). Jeśli chcesz określić kolor, to musisz go przetworzyć na te trzy podane kolory główne. Każda wartość koloru posiada zakres od 0 do 255 (wartość bajtowa). Na przykład dla czysto czerwonego koloru powinieneś użyć 255,0,0. A czysty biały kolor wymaga wartości RGB równej 255,255,255. Jak widać z powyższych przykładów określenie potrzebnego koloru w tym systemie jest bardzo trudne, ponieważ musisz posiadać dobre wyczucie mieszania i doboru kolorów.
Kolor tekstu i tła ustawiamy wywołując odpowiednio funkcje SetTextColor oraz SetBkColor i przekazując im jako parametr uchwyt kontekstu urządzenia oraz 32 bitową wartość RGB. Struktura 32 bitowej wartości RGB jest następująca:
RGB_value STRUCT unused DB 0 blue DB ? green DB ? red DB ? RGB_value ENDS
Zwróć uwagę, iż pierwszy bajt nie jest używany i powinien mieć wartość 0.
Kolejność pozostałych 3 bajtów jest odwrócona, tj. niebieski
(blue), zielony (green) oraz czerwony
(red). Jednakże w naszym programie nie skorzystamy z
tej struktury, ponieważ jest ona kłopotliwa do inicjalizacji i użycia. Zamiast
tego utworzymy makro. Makro otrzyma wartości trzech parametrów: red, green oraz
blue. Utworzy pożądaną, 32-bitową wartość RGB i umieści
ją w rejestrze
eax. Makro jest następujące:
RGB MACRO red, green, blue mov eax, red OR (green SHL 8) OR (blue SHL 16) ENDM
Czcionkę możesz "utworzyć" wywołując
CreateFont
lub CreateFontIndirect. Różnicą pomiędzy tymi
dwoma funkcjami jest to, iż CreateFontIndirect
otrzymuje tylko jeden parametr - wskazanie logicznej struktury czcionki
LOGFONT. Z tych dwóch funkcji
CreateFontIndirect jest bardziej uniwersalna,
szczególnie gdy twój program musi często zmieniać czcionki. Jednakże w
naszym przykładzie "utworzymy" tylko jedną czcionkę dla demonstracji,
zatem możemy zastosować CreateFont. Po wywołaniu
tej funkcji zwróci ona uchwyt czcionki, który musisz następnie wstawić
do kontekstu urządzenia. Po wykonaniu tej operacji wszystkie
funkcje API będą używały
wybranej czcionki.
.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 mov eax, red or (green shl 8) or (blue shl 16) ENDM .DATA ClassName DB "SimpleWinClass",0 AppName DB "Okienko z tekstem",0 TestString DB "Asembler Win32 jest prosty!" 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 255,255,0 INVOKE SetTextColor, hdc, eax RGB 0,127,127 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
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 tworzy logiczną czcionkę najbardziej zbliżoną do
podanych parametrów na podstawie dostępnych zasobów czcionek systemu.
Funkcja ta ma więcej parametrów niż jakakolwiek inna funkcja w
systemie Windows. Zwraca ona uchwyt do logicznej czcionki, który
ma być użyty przez funkcję SelectObject.
Przeanalizujemy szczegółowo jej parametry:
CreateFont PROTO nHeight: DWORD,\ nWidth: DWORD,\ nEscapement: DWORD,\ nOrientation: DWORD,\ fnWeight: DWORD,\ fdwItalic: DWORD,\ fdwUnderline: DWORD,\ fdwStrikeOut: DWORD,\ fdwCharSet: DWORD,\ fdwOutputPrecision: DWORD,\ fdwClipPrecision: DWORD,\ fdwQuality: DWORD,\ fdwPitchAndFamily: DWORD,\ lpszFace: DWORD
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
Opis podany powyżej nie jest w żaden sposób wyczerpujący. Więcej szczegółów znajdziesz w pliku pomocy dla funkcji API Win32.
INVOKE SelectObject, hdc, eax mov hfont, eax
Po otrzymaniu uchwytu do logicznej czcionki musimy użyć go do ustawienia
tej czcionki w kontekście urządzenia przez wywołanie funkcji
SelectObject. Funkcja ta umieszcza nowe obiekty
GDI takie jak pióra, pędzle i czcionki w
kontekście urządzenia, aby były używane przez funkcje
GDI. Zwraca ona uchwyt zastąpionego obiektu, który musisz
zachować dla przyszłego wywołania SelectObject.
Po tym wywołaniu każda funkcja wyprowadzająca tekst na ekran będzie
używała nowej czcionki ustawionej w kontekście urządzenia.
RGB 255,255,0 INVOKE SetTextColor, hdc, eax RGB 0,127,127 INVOKE SetBkColor, hdc, eax
Użyj makra RGB do utworzenia 32-bitowej wartości
RGB do zastosowania jako parametr dla funkcji
SetTextColor oraz
SetBkColor.
INVOKE TextOut, hdc, 0, 0, ADDR TestString, SIZEOF TestString
Do narysowania tekstu na obszarze roboczym okna wywołaj funkcję
TextOut. Tekst będzie posiadał czcionkę oraz
kolor określone wcześniej.
INVOKE SelectObject, hdc, hfont
Gdy zakończymy pracę z daną czcionką, powinniśmy odtworzyć poprzednią czcionkę w kontekście urządzenia. Zawsze powinieneś odtworzyć obiekt, który zastąpiłeś w kontekście urządzenia.
Ta sama aplikacja w Pascalu:
{******************************** ** I Liceum Ogólnokształcące ** ** w Tarnowie ** ** mgr Jerzy Wałaszek ** ********************************} program MoreText; uses Windows; function RGB(R,G,B : integer) : UINT; begin RGB := R or (G shl 8) or (b shl 16); end; function WndProc(h:HWND;uMsg:UINT;wP:WPARAM;lP:LPARAM) : longint; const OurText = 'FreePascal jest prosty'; FontName : string = 'script'; var HDevCnt: HDC; ps : PAINTSTRUCT; hf : HFONT; r : RECT; begin WndProc := 0; case uMsg of WM_DESTROY: PostQuitMessage(0); WM_PAINT : begin HDevCnt := BeginPaint(h,ps); hf := SelectObject(HDevCnt, CreateFont(24,16,0,0,400,0,0,0, OEM_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH or FF_SCRIPT,@FontName)); SetTextColor(HDevCnt,RGB(255,255,0)); SetBkColor(HDevCnt,RGB(0,127,127)); TextOut(HDevCnt,0,0,OurText,Length(OurText)); SelectObject(HDevCnt, hf); EndPaint(h,ps); else WndProc := DefWindowProc(h,uMsg,wP,lP); end; end; function WinMain(hI,hPI:HINST;CmdLine:LPSTR;cmdShow:longint) : longint; const ClassName = 'SimpleWinClass'; var wc : WndClassEx; ms : msg; h : HWnd; begin wc.cbSize := SizeOf(WndClassEx); wc.style := CS_HREDRAW or CS_VREDRAW; wc.lpfnWndProc := @WndProc; wc.cbClsExtra := 0; wc.cbWndExtra := 0; wc.hInstance := hI; wc.hbrBackground := COLOR_WINDOW + 1; wc.lpszMenuName := 0; wc.lpszClassName := ClassName; wc.hIcon := LoadIcon(0,IDI_APPLICATION); wc.hIconSm := wc.hIcon; wc.hCursor := LoadCursor(0,IDC_ARROW); RegisterClassEx(wc); h := CreateWindowEx(0,ClassName,'Nasze okno z tekstem', WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,0,0,hI,0); ShowWindow(h,CmdShow); UpdateWindow(h); while GetMessage(ms,0,0,0) do begin TranslateMessage(ms); DispatchMessage(ms); end; WinMain := ms.wParam; end; begin ExitProcess(WinMain(GetModuleHandle(0),0,0,SW_SHOWDEFAULT)); end.
Autorem
kursu jest
Iczelion. Kurs
programowania Windows znalazł się na serwerze I LO w Tarnowie za pisemną
zgodą autora. |
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe