windows环境下32位汇编语言程序设计-第33章
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
绘制区域的函数有画矩形的Rectangle,画圆角矩形的RoundRect,画多边形的Polygon,画弦的Chord,画圆饼的Pie和画椭圆的Ellipse。这些函数的使用效果见如7。4所示。
表7。4 填充函数的功能
函 数
说 明
图 例
Rectangle(hDC;x1;y1;x2;y2)
画以(x1,y1)和(x2,y2)为对角坐标的填充矩形
RoundRect(hDC;x1;y1;x2;y2;w;h)
画以(x1,y1)和(x2,y2)为对角坐标的填充矩形,四个角以一个小椭圆来画圆角,小椭圆的宽和高为w和h
函 数
说 明
图 例
Polygon(hDC;lpPoint;5)
lpPoint指向存放(x1,y1)到(x5,y5)的缓存区,函数从(x1,y1)到(x2,y2)…到(x5,y5),再回到(x1,y1),一共画5条直线并填充
Chord(hDC;x1;y1;x2;y2;
x3;y3;x4;y4)
以和Arc函数同样的方法画弧,然后连接弧的两个端点并填充
Pie(hDC;x1;y1;x2;y2;
x3;y3;x4;y4)
以和Arc函数同样的方法画弧,然后将弧的两个端点分别和椭圆中心连接并填充
Ellipse(hDC;x1;y1;x2;y2)
以(x1,y1)和(x2,y2)为对角定义一个矩形,然后画矩形相切的椭圆并填充
在这些函数中,Polygon的调用方式和Polyline很相似,只不过如果最后一点和第一点不同的话,函数自动再画一条和起始点相连的直线将整个区域闭合起来。用Polygon绘画的多边形中各条直线可能相交,Windows允许程序自行选择填充的模式,可以是表7。4中Polygon一栏中的上面那个图例(填充全部区域),也可以是下面那个图例(间隔填充区域)。可以用下面的函数切换填充的模式:
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第7章 图形操作
7。2 绘 制 图 形(6)
invoke SetPolyFillMode;_hDC;ALTERNATE ;间隔填充
invoke SetPolyFillMode;_hDC;WINDING ;填充全部区域
Chord函数和Pie函数的参数使用和画弧线的Arc函数相似,只不过Chord函数将弧线的两端直接相连,形成一个“弦”,而Pie函数将两端和圆心相连,形成一个“圆饼”,这两个函数绘画的方向同样受SetArcDirection函数设置的影响。
在例子Clock。asm中,程序在_DrawDot子程序中用Ellipse函数绘画时钟的刻度,读者也可以将程序改动一下,尝试着用Polygon画五角星来当做时钟的刻度。
除了这些函数,还有3个和矩形有关的填充函数:FillRect,FrameRect和InvertRect;这些函数不使用当前画笔画边线,也不用当前画刷填充,其中FillRect函数用指定的画刷hBrush填充一个lpRect指定的矩形区域,lpRect指向一个RECT结构;FrameRect函数用指定画刷hBrush绘画边线;InvertRect函数将lpRect指定的矩形区域中的颜色值取反。用法如下。
invoke FillRect,hDC,lpRect,hBrush
invoke FrameRect,hDC,lpRect,hBrush
invoke InvertRect,hDC,lpRect
假设背景为白色,而参数中hBrush指定的画刷为灰色画刷,那么上述3个函数的运行结果如图7。8所示。
图7。8 FillRect,FrameRect和InvertRect函数的运行结果
图中左边是FillRect的运行结果,可以看到图案没有边线;中间是FrameRect的运行结果,它用灰色画刷绘画边线,得到了一个灰色的矩形边框;右边是InvertRect的运行结果,由于底色是白色的,白色取反得到的是黑色,所以整个矩形都变成了黑色。
7。2。4 绘图模式
在前面的内容中我们都是尝试在DC上用绘图函数画出需要的图形,对于DC上被绘画上去的像素来说,相当于用画笔(或画刷)的像素点代替了原来的像素点,但Windows也可以用画笔的像素点和原来的像素点进行计算以后的值当做新的像素点,这个计算的过程就叫做光栅运算,光栅运算的方法用“光栅运算符”来定义——英文缩写是ROP(Raster Operation),ROP码是一些取反、异或、拷贝、或及与等位运算方法的组合,对于绘图函数,Windows定义了16种ROP码,如表7。5所示。
表7。5 绘图模式中可以使用的ROP码
ROP码
新像素点算法
说 明
R2_BLACK
0
总为黑色
R2_WHITE
1
总为白色
R2_NOP
像素
保持不变
R2_NOT
not(像素)
原来像素的颜色取反
R2_COPYPEN
画笔
画笔颜色
R2_NOTCOPYPEN
not(画笔)
画笔颜色取反
R2_MERGEPENNOT
画笔or not(像素)
画笔颜色与原像素颜色取反后值的复合
R2_MASKPENNOT
画笔 and not(像素)
画笔和原像素取反后值的共同色
R2_MERGENOTPEN
像素 or not(画笔)
原像素颜色与画笔取反颜色的复合
R2_MASKNOTPEN
像素 and not(画笔)
原来像素和画笔取反后的共同色
R2_MERGEPEN
像素 or 画笔
画笔颜色与原来像素的复合
R2_NOTMERGEPEN
not(像素 or 画笔)
R2_MERGEPEN再取反
R2_MASKPEN
像素 and 画笔
画笔和原来像素的共同色
R2_NOTMASKPEN
not(像素 and 画笔)
R2_MASKPEN再取反
R2_XORPEN
像素 xor 画笔
画笔和原来像素的异或值
R2_NOTXORPEN
not(像素 xor 画笔)
R2_XORPEN 再取反
表中的“像素”指DC中要绘画位置原来的像素值,画笔指要画上去的颜色值,当然ROP码影响的并不单是画笔画出的线条,同样影响用画刷填充的区域,所以读者不要被表中的“PEN”搞混淆了,这个“PEN”指的是“Pen and Brush”!
ROP为一些应用提供了方便,比如需要在背景上拖动一个图形,如果用普通的绘画方法,那么在绘画前必须保存原来背景的数据,在图形拖动后再恢复,然后在新的位置再保存、再绘画,如此重复。但如果使用R2_XORPEN或R2_NOTXORPEN的绘画模式,因为xor操作两遍就是原来的数值,所以不需保存原来的像素,在相同的地方再绘画一遍就相当于恢复原来的图形。而用R2_BLACK和R2_WHITE就相当于不管画笔和画刷是什么颜色,画出来的全部是黑色或白色。
对于一个DC来说,默认的绘图模式是R2_COPYPEN,就是用画笔或画刷的颜色替换掉原来像素的颜色。如果要设置新的绘图模式,可以使用SetROP2函数。如下面的语句将绘图模式设置为R2_NOTCOPYPEN模式,这样以后的所有的绘图函数就将以画笔或画刷取反后的颜色绘图了:
invoke SetROP2,hDC,R2_NOTCOPYPEN
如果要获取当前的绘图模式,可以使用GetROP2函数,函数返回当前的模式:
invoke GetROP2,hDC
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第7章 图形操作
7。3 创建和使用位图(1)
7。2节探讨了绘制图形的一些函数,虽然绘图操作是图形程序必不可少的一部分,但丰富多彩的界面大部分还是靠设计精美的位图来铺成的,而不是靠绘图函数一点点画出来的。在大部分程序中,使用预先设计好的位图是最普遍的做法,在这一节中,将讨论如何使用位图,并在下一节中讨论使用块传送函数对位图进行操作。
7。3。1 一个使用位图的时钟例子
本节使用另一个时钟的例子,这个时钟的背景和边框用位图组成,程序中有两套背景图片和两套边框图片可供自由选择,图7。9显示了几种不同组合下的时钟外形,最右边的是在时钟上面按下右键弹出的选择菜单。
图7。9 BmpClock时钟程序的运行结果
程序的源代码可以在所附光盘的Chapter07BmpClock目录中找到,包括汇编源程序BmpClock。asm、资源脚本文件BmpClock。rc和一些图片。
BmpClock。rc源文件如下,中间定义了一些程序中要使用的位图:
//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
#include
//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
#define ICO_MAIN 100
#define IDC_MAIN 100
#define IDC_MOVE 101
#define IDB_BACK1 100
#define IDB_CIRCLE1 101
#define IDB_BACK2 103
#define IDB_CIRCLE2 104
#define IDB_MASK2 105
//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
ICO_MAIN ICON 〃Main。ico〃
IDC_MAIN CURSOR 〃Main。cur〃
IDC_MOVE CURSOR 〃Move。cur〃
IDB_BACK1 BITMAP 〃Back1。bmp〃
IDB_CIRCLE1 BITMAP 〃Circle1。bmp〃
IDB_MASK1 BITMAP 〃Mask1。bmp〃
IDB_BACK2 BITMAP 〃Back2。bmp〃
IDB_CIRCLE2 BITMAP 〃Circle2。bmp〃
IDB_MASK2 BITMAP 〃Mask2。bmp〃
汇编源程序BmpClock。asm程序如下:
。386
。model flat; stdcall
option casemap :none
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; Include 文件定义
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
include windows。inc
include user32。inc
includelib user32。lib
include kernel32。inc
includelib kernel32。lib
include Gdi32。inc
includelib Gdi32。lib
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; Equ 等值定义
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
CLOCK_SIZE equ 150
ICO_MAIN equ 100
IDC_MAIN equ 100
IDC_MOVE equ 101
IDB_BACK1 equ 100
IDB_CIRCLE1 equ 101
IDB_MASK1 equ 102
IDB_BACK2 equ 103
IDB_CIRCLE2 equ 104
IDB_MASK2 equ 105
ID_TIMER equ 1
IDM_BACK1 equ 100
IDM_BACK2 equ 101
IDM_CIRCLE1 equ 102
IDM_CIRCLE2 equ 103
IDM_EXIT equ 104
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 数据段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
。data?
hInstance dd ?
hWinMain dd ?
hCursorMove dd ? ;Cursor when move
hCursorMain dd ? ;Cursor when normal
hMenu dd ?
hBmpBack dd ?
hDcBack dd ?
hBmpClock dd ?
hDcClock dd ?
dwNowBack dd ?
dwNowCircle dd ?
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
nst
szClassName db 'Clock';0
dwPara180 dw 180
dwRadius dw CLOCK_SIZE/2
szMenuBack1 db '使用格子背景(&A)';0
szMenuBack2 db '使用花布背景(&B)';0
szMenuCircle1 db '使用淡蓝色边框(&C)';0
szMenuCircle2 db '使用粉红色边框(&D)';0
szMenuExit db '退出(&X)。。。';0
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 代码段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
de
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 计算时钟圆周上某个角度对应的 X 坐标
; X = 圆心X + Sin(角度) * 半径
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_CalcX proc _dwDegree;_dwRadius
local @dwReturn
fild dwRadius
fild _dwDegree
fldpi
fmul ;角度*Pi
fild dwPara180
fdivp st(1);st ;角度*Pi/180
fsin ;Sin(角度*Pi/180)
fild _dwRadius
fmul ;半径*Sin(角度*Pi/180)
fadd ;X+半径*Sin(角度*Pi/180)
fistp @dwReturn
mov eax;@dwReturn
ret
_CalcX endp
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 计算时钟圆周上某个角度对应的 Y 坐标
; Y = 圆心Y … Cos(角度) * 半径
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_CalcY proc _dwDegree;_dwRadius
local @dwReturn
fild dwRadius
fild _dwDegree
fldpi
fmul
fild dwPara180
fdivp st(1);st
fcos
fild _dwRadius
fmul
fsubp st(1);st
fistp @dwReturn
mov eax;@dwReturn
ret
_CalcY endp
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 画 _dwDegree 角度的线条,半径=_dwRadius
;》》》》》》》