📄 lion-tut-c05.htm
字号:
<html>
<head>
<link rel="stylesheet" href="../../asm.css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion 的 Win32asm 教程</title>
</head>
<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<p align="center"><font size="5"><u><strong><font color="#0000FF">第五课 </font><font size="5"><u><strong><font color="#0000FF">学习更多关于“绘制”文本串的知识</font></strong></u></font></strong></u></font></p>
<hr size="1">
<p>我们将做更多的实践去了解有关文本的诸多属性如字体和颜色等。 </p>
<p><font color="#FF0000">理论:</font></p>
<p>Windows 的颜色系统是用RGB值来表示的,R 代表红色,G 代表绿色,B 代表兰色。如果您想指定一种颜色就必须给该颜色赋相关的 RGB 值,RGB
的取值范围都是从 0 到 255,譬如您想要得到纯红色,就必须对RGB赋值(255,0,0),纯白色是 (255,255,255)。从我们下面的例子中您可以看出来要想运用好这套基于数字的颜色系统并不容易,这要求您必须对混色和颜色匹配有良好的感觉。</p>
<p> 您可以用函数 SetTextColor 和 SetBkColor 来“绘制”背景色和字符颜色,但是必须传递一个“设备环境”的句柄和 RGB 值作为参数。RGB
的结构体的定义如下: </p>
<p>RGB_value struct<br>
unused db 0<br>
blue db ?<br>
green db ?<br>
red db ?<br>
RGB_value ends</p>
<p> 其中第一字节为 0 而且始终为 0,其它三个字节分别表示兰色、绿色和红色,刚好和 RGB 的次序相反。这个结构体用起来挺别扭,所以我们重新定义一个宏用它来代替。该宏接收红绿蓝三个参数,并在
eax 寄存器中返回 32 位的 RGB 值,宏的定义如下:</p>
<p> RGB macro red,green,blue<br>
xor eax,eax<br>
mov ah,blue<br>
shl eax,8<br>
mov ah,green<br>
mov al,red<br>
endm </p>
<p>您可以把该宏放到头文件中以方便使用。 </p>
<p>您可以调用 CreateFont 和 CreateFontIndirect 来创建自己的字体,这两个函数的差别是前者要求 您传递一系列的参数,而后着只要传递一个指向
LOGFONT 结构的指针。这样就使得后者使用起来更方便,尤其当您需要频繁创建字体时。在我们的例子中由于只要创建一种字体,故用 CreateFont 就足够了。在调用该函数后会返回所创建的字体的句柄,然后把该句柄选进“设备环境”使其成为当前字体,随后所有的“绘制”文本串的函数在被调用时都要把该句柄作为一个参数传递
</p>
<p><font color="#FF0000">例子:</font></p>
<p> <font color="#006666">.386 <br>
.model flat,stdcall <br>
option casemap:none </font></p>
<p><font color="#006666">WinMain proto :DWORD,:DWORD,:DWORD,:DWORD </font>
<p><font color="#006666">include \masm32\include\windows.inc <br>
include \masm32\include\user32.inc <br>
include \masm32\include\kernel32.inc <br>
include \masm32\include\gdi32.inc <br>
includelib \masm32\lib\user32.lib <br>
includelib \masm32\lib\kernel32.lib <br>
includelib \masm32\lib\gdi32.lib </font>
<p><font color="#006666">RGB macro red,green,blue <br>
xor eax,eax <br>
mov ah,blue <br>
shl eax,8 <br>
mov ah,green <br>
mov al,red <br>
endm </font>
<p><font color="#006666">.data <br>
ClassName db "SimpleWinClass",0 <br>
AppName db "Our First Window",0 <br>
TestString db "Win32 assembly is great and easy!",0 <br>
FontName db "script",0 </font>
<p><font color="#006666">.data? <br>
hInstance HINSTANCE ? <br>
CommandLine LPSTR ? </font>
<p><font color="#006666">.code <br>
start: <br>
invoke GetModuleHandle, NULL <br>
mov hInstance,eax <br>
invoke GetCommandLine<br>
mov CommandLine,eax<br>
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
<br>
invoke ExitProcess,eax </font>
<p><font color="#006666">WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
<br>
LOCAL wc:WNDCLASSEX <br>
LOCAL msg:MSG <br>
LOCAL hwnd:HWND <br>
mov wc.cbSize,SIZEOF WNDCLASSEX <br>
mov wc.style, CS_HREDRAW or CS_VREDRAW <br>
mov wc.lpfnWndProc, OFFSET WndProc <br>
mov wc.cbClsExtra,NULL <br>
mov wc.cbWndExtra,NULL <br>
push hInst <br>
pop wc.hInstance <br>
mov wc.hbrBackground,COLOR_WINDOW+1 <br>
mov wc.lpszMenuName,NULL <br>
mov wc.lpszClassName,OFFSET ClassName <br>
invoke LoadIcon,NULL,IDI_APPLICATION <br>
mov wc.hIcon,eax <br>
mov wc.hIconSm,eax <br>
invoke LoadCursor,NULL,IDC_ARROW <br>
mov wc.hCursor,eax <br>
invoke RegisterClassEx, addr wc <br>
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
<br>
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
<br>
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
<br>
hInst,NULL <br>
mov hwnd,eax <br>
invoke ShowWindow, hwnd,SW_SHOWNORMAL <br>
invoke UpdateWindow, hwnd <br>
.WHILE TRUE <br>
invoke GetMessage, ADDR msg,NULL,0,0 <br>
.BREAK .IF (!eax) <br>
invoke TranslateMessage, ADDR msg <br>
invoke DispatchMessage, ADDR msg <br>
.ENDW <br>
mov eax,msg.wParam <br>
ret <br>
WinMain endp </font>
<p><font color="#006666">WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
<br>
LOCAL hdc:HDC <br>
LOCAL ps:PAINTSTRUCT <br>
LOCAL hfont:HFONT </font>
<p><font color="#006666"> .IF uMsg==WM_DESTROY <br>
invoke PostQuitMessage,NULL <br>
.ELSEIF uMsg==WM_PAINT <br>
invoke BeginPaint,hWnd, ADDR ps <br>
mov hdc,eax <br>
invoke CreateFont,24,16,0,0,400,0,0,0,OEM_CHARSET,\
<br>
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\ <br>
DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\ <br>
ADDR FontName <br>
invoke SelectObject, hdc, eax <br>
mov hfont,eax <br>
RGB 200,200,50
<br>
invoke SetTextColor,hdc,eax <br>
RGB 0,0,255 <br>
invoke SetBkColor,hdc,eax <br>
invoke TextOut,hdc,0,0,ADDR TestString,SIZEOF
TestString <br>
invoke SelectObject,hdc, hfont <br>
invoke EndPaint,hWnd, ADDR ps <br>
.ELSE <br>
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
<br>
ret <br>
.ENDIF <br>
xor eax,eax <br>
ret <br>
WndProc endp </font>
<p><font color="#006666">end start </font>
<p><font color="#FF0000">分析:</font></p>
<p> CreateFont 函数产生一种逻辑字体,它尽可能地接近参数中指定的各相关值。这个函数大概是所有 Windows API函数中所带参数最多的一个。它返回一个指向逻辑字体的句柄供调用
SelectObject 函数使用。下面我们详细讲解该函数的参数:</p>
<p> <font color="#006666">CreateFont proto \<br>
nHeight:DWORD,\<br>
nWidth:DWORD,\<br>
nEscapement:DWORD,\<br>
nOrientation:DWORD,\<br>
nWeight:DWORD,\ <br>
cItalic:DWORD,\ <br>
cUnderline:DWORD,\<br>
cStrikeOut:DWORD,\<br>
cCharSet:DWORD,\<br>
cOutputPrecision:DWORD,\<br>
cClipPrecision:DWORD,\<br>
cQuality:DWORD,\<br>
cPitchAndFamily:DWORD,\<br>
lpFacename:DWORD</font></p>
<p> nHeight: 希望使用的字体的高度,0为缺省。<br>
nWidth: 希望使用的字体的宽度,一般情况下最好用0, 这样 Windows 将会自动为您选择一个和高度匹配的值。因为在我们的例子中那样做的话会使得字符因太小而无法显示,所以
我 们设定它为16。<br>
nEscapement: 每一个字符相对前一个字符的旋转角度,一般设成0。900代表转90度,1800转190度,2700转270度。<br>
nOrientation: 字体的方向。<br>
nWeight: 字体笔画的粗细。</p>
<p> Windows 为我们预定义了如下值: </p>
<p>FW_DONTCARE 等于 0<br>
FW_THIN 等于 100<br>
FW_EXTRALIGHT 等于 200<br>
FW_ULTRALIGHT 等于 200<br>
FW_LIGHT 等于 300<br>
FW_NORMAL 等于 400<br>
FW_REGULAR 等于 400<br>
FW_MEDIUM 等于 500<br>
FW_SEMIBOLD 等于 600<br>
FW_DEMIBOLD 等于 600<br>
FW_BOLD 等于 700<br>
FW_EXTRABOLD 等于 800<br>
FW_ULTRABOLD 等于 800<br>
FW_HEAVY 等于 900<br>
FW_BLACK 等于 900</p>
<p> cItalic: 0为正常,其它值为斜体。 <br>
cUnderline: 0为正常,其它值为有下划线。<br>
cStrikeOut: 0为正常,其它值为删除线。<br>
cCharSet: 字体的字符集。一般选择OEM_CHARSET,它使得 Windows 会选用和操作系统相关的字符集。<br>
cOutputPrecision: 指定我们选择的字体接近真实字体的精度。 一般选用OUT_DEFAULT_PRECIS,它决定了缺省的映射方式。<br>
cClipPrecision: 指定我们选择的字体在超出裁剪区域时的裁剪精度。 一般选用CLIP_DEFAULT_PRECIS,它决定了裁剪精度。<br>
cQuality: 指定输出字体的质量。它指出GDI应如何尽可能的接近真实 字体,一共有三种方式:DEFAULT_QUALITY, PROOF_QUALITY
和DRAFT_QUALITY。<br>
cPitchAndFamily:字型和字体家族。<br>
lpFacename: 指定字体的名称。 </p>
<p>上面的描述不一定好理解,您如果要的到更多的信息,应参考 WIN32 API 指南。 </p>
<p><font color="#006666">invoke SelectObject, hdc, eax<br>
mov hfont,eax</font></p>
<p> 在我们得到了指向逻辑字体的句柄后必须调用 SelectObject 函数把它选择进“设备环境”,我们还可以调用该函数把诸如此类的像颜色、笔、画刷
等GDI对象选进“设备环境”。该函数会返回一个旧的“设备环境”的句柄。您必须保存该句柄,以便在完成“绘制”工作后再把它选回。在调用 SelectObject
函数后一切的绘制函数都是针对该“设备环境”的。 </p>
<p><font color="#006666">RGB 200,200,50<br>
invoke SetTextColor,hdc,eax<br>
RGB 0,0,255 <br>
invoke SetBkColor,hdc,eax</font></p>
<p> 我们用宏 RGB 产生颜色,然后分别调用 SetTextColor 和 SetBkColor。</p>
<p> <font color="#006666">invoke TextOut,hdc,0,0,ADDR TestString,SIZEOF TestString</font></p>
<p> 我们调用 TextOut 在客户区用我们前面选定的字体和颜色“绘制”文本串。 </p>
<p><font color="#006666">invoke SelectObject,hdc, hfont</font></p>
<p> 在我们“绘制”完成后,必须恢复“设备环境”。我们必须每一次都这么做。 </p>
<hr size="1">
<div align="center">
<script language="JavaScript1.1" src=http://ad.t2t2.com/textclick.asp?user=bigluo&style=4&bkcolor=no></script>
<br>
</div>
<!-- 10:1 文本广告交换 -->
<div align="center">
<script language="JavaScript1.1" src=http://coolsite21.com:90/c21.dll?Type=PT&id=1047&col=6&ReferID=1047&v=0></script>
<!-- 10:1 文本广告交换 --> </div>
<hr size="1">
<br>
<div align="center"> 翻译:Lxx,校对:LuoYunBin's Win32 ASM Page,<a href="http://asm.yeah.net">http://asm.yeah.net</a></div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -