WIN32彙編: 5.學習更多的關於文本的知識

第五課 學習更多關於“繪製”文本串的知識


我們將做更多的實踐去了解有關文本的諸多屬性如字體和顏色等。

理論:

Windows 的顏色系統是用RGB值來表示的,R 代表紅色,G 代表綠色,B 代表蘭色。如果您想指定一種顏色就必須給該顏色賦相關的 RGB 值,RGB 的取值範圍都是從 0 到 255,譬如您想要得到純紅色,就必須對RGB賦值(255,0,0),純白色是 (255,255,255)。從我們下面的例子中您可以看出來要想運用好這套基於數字的顏色系統並不容易,這要求您必須對混色和顏色匹配有良好的感覺。

您可以用函數 SetTextColor 和 SetBkColor 來“繪製”背景色和字符顏色,但是必須傳遞一個“設備環境”的句柄和 RGB 值作爲參數。RGB 的結構體的定義如下:

RGB_value struct
unused db 0
blue db ?
green db ?
red db ?
RGB_value ends

其中第一字節爲 0 而且始終爲 0,其它三個字節分別表示蘭色、綠色和紅色,剛好和 RGB 的次序相反。這個結構體用起來挺彆扭,所以我們重新定義一個宏用它來代替。該宏接收紅綠藍三個參數,並在 eax 寄存器中返回 32 位的 RGB 值,宏的定義如下:

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

您可以把該宏放到頭文件中以方便使用。

您可以調用 CreateFont 和 CreateFontIndirect 來創建自己的字體,這兩個函數的差別是前者要求 您傳遞一系列的參數,而後着只要傳遞一個指向 LOGFONT 結構的指針。這樣就使得後者使用起來更方便,尤其當您需要頻繁創建字體時。在我們的例子中由於只要創建一種字體,故用 CreateFont 就足夠了。在調用該函數後會返回所創建的字體的句柄,然後把該句柄選進“設備環境”使其成爲當前字體,隨後所有的“繪製”文本串的函數在被調用時都要把該句柄作爲一個參數傳遞

例子:

.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 assembly is great and easy!",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

分析:

CreateFont 函數產生一種邏輯字體,它儘可能地接近參數中指定的各相關值。這個函數大概是所有 Windows API函數中所帶參數最多的一個。它返回一個指向邏輯字體的句柄供調用 SelectObject 函數使用。下面我們詳細講解該函數的參數:

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: 希望使用的字體的高度,0爲缺省。
nWidth: 希望使用的字體的寬度,一般情況下最好用0, 這樣 Windows 將會自動爲您選擇一個和高度匹配的值。因爲在我們的例子中那樣做的話會使得字符因太小而無法顯示,所以 我 們設定它爲16。
nEscapement: 每一個字符相對前一個字符的旋轉角度,一般設成0。900代表轉90度,1800轉190度,2700轉270度。
nOrientation: 字體的方向。
nWeight: 字體筆畫的粗細。

Windows 爲我們預定義瞭如下值:

FW_DONTCARE 等於 0
FW_THIN 等於 100
FW_EXTRALIGHT 等於 200
FW_ULTRALIGHT 等於 200
FW_LIGHT 等於 300
FW_NORMAL 等於 400
FW_REGULAR 等於 400
FW_MEDIUM 等於 500
FW_SEMIBOLD 等於 600
FW_DEMIBOLD 等於 600
FW_BOLD 等於 700
FW_EXTRABOLD 等於 800
FW_ULTRABOLD 等於 800
FW_HEAVY 等於 900
FW_BLACK 等於 900

cItalic: 0爲正常,其它值爲斜體。
cUnderline: 0爲正常,其它值爲有下劃線。
cStrikeOut: 0爲正常,其它值爲刪除線。
cCharSet: 字體的字符集。一般選擇OEM_CHARSET,它使得 Windows 會選用和操作系統相關的字符集。
cOutputPrecision: 指定我們選擇的字體接近真實字體的精度。 一般選用OUT_DEFAULT_PRECIS,它決定了缺省的映射方式。
cClipPrecision: 指定我們選擇的字體在超出裁剪區域時的裁剪精度。 一般選用CLIP_DEFAULT_PRECIS,它決定了裁剪精度。
cQuality: 指定輸出字體的質量。它指出GDI應如何儘可能的接近真實 字體,一共有三種方式:DEFAULT_QUALITY, PROOF_QUALITY 和DRAFT_QUALITY。
cPitchAndFamily:字型和字體家族。
lpFacename: 指定字體的名稱。

上面的描述不一定好理解,您如果要的到更多的信息,應參考 WIN32 API 指南。

invoke SelectObject, hdc, eax
mov hfont,eax

在我們得到了指向邏輯字體的句柄後必須調用 SelectObject 函數把它選擇進“設備環境”,我們還可以調用該函數把諸如此類的像顏色、筆、畫刷 等GDI對象選進“設備環境”。該函數會返回一箇舊的“設備環境”的句柄。您必須保存該句柄,以便在完成“繪製”工作後再把它選回。在調用 SelectObject 函數後一切的繪製函數都是針對該“設備環境”的。

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

我們用宏 RGB 產生顏色,然後分別調用 SetTextColor 和 SetBkColor。

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

我們調用 TextOut 在客戶區用我們前面選定的字體和顏色“繪製”文本串。

invoke SelectObject,hdc, hfont

在我們“繪製”完成後,必須恢復“設備環境”。我們必須每一次都這麼做。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章