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环境的配置来输出我们的字符串。。。

Fasm---Win32汇编学习7相关推荐

  1. Win32汇编学习——windows汇编语法(小甲鱼教程)

    Win32汇编学习--windows汇编语法(小甲鱼教程) 1)指令集 .386 语句是汇编语句的伪指令,类似指令有:.8086 . .186  ..286  ..386/.386p  . .486/ ...

  2. Win32汇编学习笔记之基础篇

    基础篇 第一章 背景知识 1.1 Win32的软硬件平台 1.1.1    80x86系列处理器简史 Win32可以在多种硬件平台上运行,但使用最广泛的硬件平台是基于Intel公司80x86系列处理器 ...

  3. Win32汇编学习——windows基础知识(小甲鱼教程)

    <Win32汇编语言程序设计>(小甲鱼) 1)windows特权保护机制 1)80386的中断和异常 2)80386的保护机制 3)Windows的保护机制 2)80x86处理器的工作模式 ...

  4. Win32汇编学习(10):对话框(1)

    现在我们开始学习一些有关GUI编程的有趣的部分:以对话框为主要界面的应用程序. 理论: 如果您仔细关注过前一个程序就会发现:您无法按TAB键从一个子窗口控件跳到另一个子窗口控件,要想转移的话只有 用鼠 ...

  5. Win32汇编学习(7):鼠标输入消息

    这次我们将学习如何在我们的窗口过程函数中处理鼠标按键消息.例子演示了如何等待鼠标左键按下消息,我们将在按下的位置显示一个字符串. 理论: 和处理键盘输入一样,WINDOWS将捕捉鼠标动作并把它们发送到 ...

  6. Win32汇编学习笔记(罗云彬)(二)

    1.代码段的属性是由PE头部中的属性位决定的,通过编辑exe文件,把代码段的属性位改为可写,程序就允许修改自己的代码段.典型的应用如:这对可执行文件的压缩软件和加壳软件. 2.堆栈段的内存属性是可读可 ...

  7. win32汇编学习的一些摘要

    sizeof 变量名,数据类型或数据结构 lengthof 变量名.数据类型或数据结构名 sizeof 伪指令可以取得变量.数据类型或数据结构以字节为单位的长度,lengthof可以取得变量中数据的项 ...

  8. Win32汇编学习[7]: 定义符号常量(=、EQU、TEXTEQU)

    关于符号常量 =的例子 .386 .model flat,stdcall include   windows.inc include   kernel32.inc include   masm32.i ...

  9. Win32汇编学习笔记(罗云彬)(一)

    1.80x86处理器的3种工作模式:实模式.保护模式和虚86模式 ;>>>>>>>>>>>>>>>>&g ...

  10. 【Win32汇编】学习Win32汇编

    学习Win32汇编(Windows下的32位汇编) 第一个程序Hello world 控制台输出(新建Console App工程) Debug输出(新建Win32 App工程) 后面代码的头文件在这里 ...

最新文章

  1. mysql 替换某个字段中的某个字符
  2. sybase存储过程修改
  3. linux elf格式文件详细分析
  4. 7-6 动物 (15 分)
  5. Asp.net 2.0 自定义控件开发专题讲解[为用户控件增加DataSource属性, 能够自动识别不同数据源](示例代码下载)...
  6. oracle表的管理,Oracle表的管理
  7. 用友仓库档案boot直接访问html,图文解析用友仓库软件怎样设置档案?
  8. python代码大全-python中的字典用法大全的代码
  9. Python返回多个值
  10. Mac 下如保查看二进制文件,比如.heic文件
  11. 如何找到最新的RFC文档
  12. SourceTree 删除记住的账户
  13. 中国慕课moocpython答案_中国大学慕课moocPython编程基础答案
  14. Iphone蓝牙通信
  15. linux电脑滚轮不能用,图文详解电脑鼠标滚轮不动了怎么办_电脑鼠标滚轮不能用的三种解决方法-系统城...
  16. 存储桶上传策略和签名 URL的绕过及利用
  17. Unity开发游戏--2D坦克大战(一)
  18. 【Oracle】plsql连接64位的Oracle
  19. NFC中国-中国第一NFC论坛,NFC中文论坛+NFC技术社区+NFC_电子发烧友网【申明:来源于网络】
  20. 统计学习:现代机器学习

热门文章

  1. DIY电脑硬件之显卡的选择
  2. ES-endpoint
  3. [火星]汉芯被证实造假
  4. Vue项目启动后自动打开浏览器
  5. Abaqus线性动态分析之模态与响应谱分析(附INP文件)
  6. Python Pickle任意代码执行漏洞
  7. 新手炼丹师的调参内经——深度学习涨点技巧总结
  8. 三大运营商争夺iPhone,活体免费
  9. 单臂路由配置(H3C)
  10. PDF怎么转换成TXT文本?这2个方法简单还免费