Fasm---Win32汇编学习7

         Fasm---Win32汇编学习7

学习更多关于“绘制”文本串的知识

 

我们将做更多的实践去了解有关文本的诸多属性如字体和颜色等。

理论:

Windows 的颜色系统是用RGB值来表示的,R 代表红色,G 代表绿色,B 代表兰色。如果您想指定一种颜色就必须给该颜色赋相关的 RGB 值,RGB 的取值范围都是从 0 到 255,譬如您想要得到纯红色,就必须对RGB赋值(255,0,0),纯白色是 (255,255,255)。从我们下面的例子中您可以看出来要想运用好这套基于数字的颜色系统并不容易,这要求您必须对混色和颜色匹配有良好的感觉。

您可以用函数 SetTextColor 和 SetBkColor 来“绘制”背景色和字符颜色,但是必须传递一个“设备环境”的句柄和 RGB 值作为参数。RGB 的结构体的定义如下:

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

    其中第一字节为 0 而且始终为 0,其它三个字节分别表示兰色、绿色和红色,刚好和 RGB 的次序相反。这个结构体用起来挺别扭,所以我们重新定义一个宏用它来代替。该宏接收红绿蓝三个参数,并在 eax 寄存器中返回 32 位的 RGB 值,宏的定义如下:

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

 


您可以把该宏放到头文件中以方便使用。

    您可以调用 CreateFont 和 CreateFontIndirect 来创建自己的字体,这两个函数的差别是前者要求 您传递一系列的参数,而后着只要传递一个指向 LOGFONT 结构的指针。这样就使得后者使用起来更方便,尤其当您需要频繁创建字体时。在我们的例子中由于只要创建一种字体,故用 CreateFont 就足够了。在调用该函数后会返回所创建的字体的句柄,然后把该句柄选进“设备环境”使其成为当前字体,随后所有的“绘制”文本串的函数在被调用时都要把该句柄作为一个参数传递 。

 



例子:

format PE GUI 4.0
include 'win32ax.inc'


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

macro memmov [dst, src]
{
common
push [src]
pop [dst]
}

ID_TIMER1 equ 100
;************************数据********************************
szClassName db 'first Windows',0
szWndName db '我的第一个程序',0
szFontName db 'mefont',0
szCommand dd ?
hIcon rd 1
hInstanse rd 1
hCursor rd 1
hWnd rd 1
systime SYSTEMTIME

entry $
invoke GetModuleHandle,NULL
mov [hInstanse], eax
invoke GetCommandLine,NULL
mov [szCommand], eax
stdcall _WinMain,hInstanse, NULL, [szCommand], SW_SHOWDEFAULT
invoke ExitProcess,NULL

proc _WinMain hInstance:DWORD, hPrevInstance:DWORD, lpCmdLine:DWORD, nCmdShow:DWORD
local @wc : WNDCLASSEX
local @msg : MSG


invoke RtlZeroMemory,addr @wc,sizeof.WNDCLASSEX
invoke LoadIcon,NULL, IDI_WINLOGO
mov [hIcon], eax
invoke LoadCursor,NULL, IDC_ARROW
mov [hCursor], eax
mov [@wc.cbSize], sizeof.WNDCLASSEX
mov [@wc.style], CS_HREDRAW or CS_VREDRAW
mov [@wc.lpfnWndProc], _WndProc
mov [@wc.cbClsExtra], NULL
mov [@wc.cbWndExtra], NULL
memmov @wc.hInstance, hInstance
memmov @wc.hIcon, hIcon
memmov @wc.hCursor, hCursor
mov [@wc.hbrBackground], COLOR_WINDOW
mov [@wc.lpszMenuName], NULL
mov [@wc.lpszClassName], szClassName
;注册窗口类
invoke RegisterClassEx,addr @wc
;建立窗口

invoke CreateWindowEx, NULL, szClassName, szWndName,/
WS_OVERLAPPEDWINDOW,/
100, 100, 600, 400,/
NULL, NULL, [hInstanse], NULL
mov [hWnd], eax
invoke ShowWindow,[hWnd],SW_SHOWNORMAL
invoke UpdateWindow,[hWnd]

GetMsg:
invoke GetMessage,addr @msg, NULL, 0, 0
or eax, eax
jz EndMsg
invoke TranslateMessage,addr @msg
invoke DispatchMessage,addr @msg
jmp GetMsg


EndMsg:
mov eax, [@msg.wParam]
ret
endp



proc _WndProc uses ebx esi edi,hWnd:DWORD, wMsg:DWORD, wParam:DWORD, lParam:DWORD
local @hdc:DWORD
local @ps : PAINTSTRUCT
local @rect: RECT
local @hfont:DWORD
cmp [wMsg], WM_DESTROY
jz Quit
cmp [wMsg], WM_PAINT
jz PAIT
invoke DefWindowProc,[hWnd],[wMsg],[wParam],[lParam]
ret



PAIT:
invoke BeginPaint,[hWnd], addr @ps
mov [@hdc], eax ;保存获得显示缓冲区的显示描述表
invoke CreateFont,0,16,0,0,400,0,0,0,OEM_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,/
                        DEFAULT_QUALITY, DEFAULT_PITCH or FF_SCRIPT,/
                        szFontName
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,szWndName,15
invoke SelectObject,[@hdc], [@hfont]

invoke EndPaint,[hWnd], addr @ps
jmp endWnd

Quit:
invoke PostQuitMessage,NULL
jmp endWnd


endWnd:
xor eax,eax
ret
endp


;///输入表


section '.import' data import readable writeable


library kernel32, 'kernel32.dll',/
user32, 'user32.dll',/
gdi32, 'gdi32.dll'
include 'api/kernel32.inc'
include 'api/user32.inc'
include 'api/gdi32.inc'

 

 

 

分析

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: 指定字体的名称。

上面的描述不一定好理解,更详细的内容请参看MSDN。

 

其实上面的代码很多在上上节课我们已经讲解了,只有很少的一部分不同。。。

我们来学习。

 

invoke BeginPaint,[hWnd], addr @ps
mov [@hdc], eax ;保存DC
invoke CreateFont,0,16,0,0,400,0,0,0,OEM_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,/
                        DEFAULT_QUALITY, DEFAULT_PITCH or FF_SCRIPT,/
                        szFontName
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,szWndName,15
invoke SelectObject,[@hdc], [@hfont]

invoke EndPaint,[hWnd], addr @ps

 

译者注:

   首先这里要再次讲解下设备环境。设备环境也经常简写为DC,它是用来管理访问显示和打印设备的工具。我们在windows中不是直接写入屏幕,我们是通过获得设备环境的句柄,使用该句柄来画设备环境,然后windows会进行判断并且从我们的设备环境中获得相应的像素显示到屏幕上。

    BeginPaint只能在WM_PAINT消息中使用,它将返回DC的句柄。。在WM_PAINT消息期间,应用程序经常在屏幕上执行绘图操作。Windows将绘图视为低级的任务,这样做是很恰当的,不然可能你只要显示一个小变化windows就发送WM_PAINT消息,这会造成WM_PAINT消息泛滥。通过处理正在等待的消息允许应用程序完成它所有的挂起任务,这将是无效区域可以很高效的一次性画出。

 

   当然有些时候画图程序也应该立即执行,例如当某个字符按下,我们必须马上将它输送到我们的屏幕上。要想在WM_PAINT消息进行绘图,你必须调用GetDC。

   GetDc函数获得窗口客户区部分的DC的句柄。

那么这里我们首先调用BeginPaint来获得我们的设备环境的句柄,并且将我们的无效区域设置为有效。然后

mov [@hdc], eax 保存我们的设备环境句柄,以备后用。

然后调用CreateFont函数来创建字体,返回的是我们创建字体的句柄,这个时候我们通过SelectObject函数来将我们创建的字体句柄选入到我们的dc中,刚我已经说了windows是通过设备环境句柄来绘画DC的。然后这个SelectObject返回的是先前选择的对象,也就是之前的字体对象以便在完成“绘制”工作后再把它选回。

此时通过调用SetTextColor和SetBkColor函数来设置字体和背景色的颜色。最后通过TextOut函数输出我们的字符串。因为此时windows会检测到当前我们的DC环境,然后按照DC环境的配置来输出我们的字符串。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值