爱爱小说网 > 其他电子书 > windows环境下32位汇编语言程序设计 >

第29章

windows环境下32位汇编语言程序设计-第29章

小说: windows环境下32位汇编语言程序设计 字数: 每页3500字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




                    local   @stRect:RECT

 

                    invoke  GetDC;hWin1

                    mov     @hDc1;eax

                    invoke  GetDC;hWin2

                    mov     @hDc2;eax

                    invoke  GetClientRect;hWin1;addr @stRect

                    invoke  BitBlt;@hDc2;0;0;@stRect。right;@stRect。bottom;



 
来源:电子工业出版社 作者:罗云彬 上一页         回书目         下一页          
上一页         回书目         下一页          
  


第7章 图形操作


7。1 GDI原理(3)

    
                            @hDc1;0;0;SRCCOPY

                    invoke  ReleaseDC;hWin1;@hDc1

                    invoke  ReleaseDC;hWin2;@hDc2

                    ret

 

_ProcTimer      endp

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; 窗口过程

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

_ProcWinMain        proc        uses ebx edi esi;hWnd;uMsg;wParam;lParam

                    local   @stPs:PAINTSTRUCT

                    local   @stRect:RECT

                    local   @hDc

 

                    mov     eax;uMsg

                    mov     ecx;hWnd

;********************************************************************

                    。if eax   WM_PAINT && ecx  hWin1

                        invoke  BeginPaint;hWnd;addr @stPs

                        mov     @hDc;eax

                        invoke  GetClientRect;hWnd;addr @stRect

                        invoke  DrawText;@hDc;addr szText;…1;

                                addr @stRect;

                                DT_SINGLELINE or DT_CENTER or DT_VCENTER

                        invoke  EndPaint;hWnd;addr @stPs

;********************************************************************

                    。elseif eax   WM_CLOSE

                            invoke  PostQuitMessage;NULL

                            invoke  DestroyWindow;hWin1

                            invoke  DestroyWindow;hWin2

;********************************************************************

                    。else

                            invoke  DefWindowProc;hWnd;uMsg;wParam;lParam

                            ret

                    。endif

;********************************************************************

                    xor eax;eax

                    ret

 

_ProcWinMain    endp

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

_WinMain        proc

                local   @stWndClass:WNDCLASSEX

                local   @stMsg:MSG

                local   @hTimer

            

                invoke  GetModuleHandle;NULL

                mov     hInstance;eax

                invoke  RtlZeroMemory;addr @stWndClass;sizeof @stWndClass

;********************************************************************

                invoke  LoadCursor;0;IDC_ARROW

                mov     @stWndClass。hCursor;eax

                push        hInstance

                pop     @stWndClass。hInstance

                mov     @stWndClass。cbSize;sizeof WNDCLASSEX

                mov     @stWndClass。style;CS_HREDRAW or CS_VREDRAW

                mov     @stWndClass。lpfnWndProc;offset _ProcWinMain

                mov     @stWndClass。hbrBackground;COLOR_WINDOW + 1

                mov     @stWndClass。lpszClassName;offset szClass1

                invoke  RegisterClassEx;addr @stWndClass

                invoke  CreateWindowEx;WS_EX_CLIENTEDGE;offset szClass1;

                        offset szCaption1;WS_OVERLAPPEDWINDOW;

                        450;100;300;300;

                        NULL;NULL;hInstance;NULL

                mov     hWin1;eax

                invoke  ShowWindow;hWin1;SW_SHOWNORMAL

                invoke  UpdateWindow;hWin1

;********************************************************************

                mov     @stWndClass。lpszClassName;offset szClass2

                invoke  RegisterClassEx;addr @stWndClass

                invoke  CreateWindowEx;WS_EX_CLIENTEDGE;offset szClass2;

                        offset szCaption2;WS_OVERLAPPEDWINDOW;

                        100;100;300;300;

                        NULL;NULL;hInstance;NULL

                mov     hWin2;eax

                invoke  ShowWindow;hWin2;SW_SHOWNORMAL

                invoke  UpdateWindow;hWin2

;********************************************************************

; 设置定时器

;********************************************************************

                invoke  SetTimer;NULL;NULL;100;addr _ProcTimer

                mov @hTimer;eax

;********************************************************************

; 消息循环

;********************************************************************

                。while  TRUE

                        invoke  GetMessage;addr @stMsg;NULL;0;0

                        。break  。if eax  0

                        invoke  TranslateMessage;addr @stMsg

                        invoke  DispatchMessage;addr @stMsg

                。endw

;********************************************************************

; 清除定时器

;********************************************************************

                invoke  KillTimer;NULL;@hTimer

                ret

 

_WinMain        endp

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

start:

                call        _WinMain

                invoke  ExitProcess;NULL

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

                end     start

这个程序的代码用到的大部分知识都是前面各章已经讲到的,在_WinMain中,用一个同样的窗口类建立了两个窗口,两个窗口属于同一个窗口类,所以它们的窗口过程都是_ProcWinMain,为了关闭任何一个窗口都可以结束程序,WM_CLOSE消息中用DestroyWindow函数摧毁了两个窗口。程序设置了一个周期为100 ms的定时器,Windows会每隔100 ms调用_ProcTimer子程序。在_ProcTimer中,将其中一个窗口的客户区拷贝到另一个窗口的客户区中,方法是通过GetDC获取窗口的DC句柄,并用BitBlt函数完成拷贝工作(这些函数的具体用法在下面的内容中会讲到),所以在右边的窗口显示了一句“Win32 Assembly; Simple and powerful!”,左边的窗口中也会出现这句话。

这个程序能演示出什么效果来呢?图7。2就是程序运行的结果,屏幕上的两个并排的正方形窗口就是DcCopy程序建立的窗口,程序每100 ms将右边窗口的客户区拷贝到左边的窗口客户区中,通过左边窗口的客户区就可以了解右边客户区DC对应的究竟是什么内容。


图7。2  DcCopy程序的运行结果



 
来源:电子工业出版社 作者:罗云彬 上一页         回书目         下一页          
上一页         回书目         下一页          
  


第7章 图形操作


7。1 GDI原理(4)

    
   现在用其他程序将右边窗口客户区的一部分覆盖掉,通过左边窗口的变化可以惊奇地发现:右边窗口客户区的内容并不是程序自己输出到客户区的那句文本,而是以客户区为矩形区域的屏幕上我们真正看到的东西,它竟然包括其他窗口覆盖在上面的东西。这就意味着,扫雷游戏和纸牌游戏通过自己客户区对应的设备环境画图形,图形数据竟然画到了DcCopy窗口客户区对应的设备环境中。

这个例子验证了“设备环境”只是“环境”而不是“设备”,它并不存储发给它的图形数据,图形数据透过它写到了它所描述的“设备”上,每个窗口客户区的“设备环境”对应的设备都是屏幕,但它们在位置上可能重叠,所以向一个窗口的客户区写数据相当于同时写了下层窗口的客户区。

为了让当前激活的窗口在视觉上保持在最上面,下层窗口向自己客户区写的内容首先要经过Windows的“过滤”,只有没有被其他窗口覆盖掉的部分才真正被写到了屏幕上。

读者应该时刻提醒自己——“设备环境”只是一个环境,是设备属性的一组定义,程序输出的图形数据透过“设备环境”被定向到了具体的设备上,“设备环境”本身并不存储这些数据(在这里也可以看出Device Context中Context一词的含义:设备环境的上面是应用程序,下面是具体设备,而它是用来“联系上下关系”用的)。

读者可能认为:屏幕上的窗口就像放在桌面上的一张张纸,虽然一张纸可能暂时被另一张遮住,但纸上写的东西还是存在的,移开另一张纸就可以再次露出来。但实际情况是:桌面更像一个用粉笔写的公告黑板,一个窗口相当于划了一块空间写告示,写另一个告示的时候要把老告示的内容擦去一部分以便写新的内容,擦去的东西也就不存在了,如果要恢复老告示,那么必须把擦去的部分重新写上去。

2。 获取设备环境句柄

要想对任何设备绘图,首先必须获取设备的“设备环境句柄”(hDC),几乎所有的GDI函数的操作目标都是hDC,在程序中得到一个hDC有几种方法。

最常用的方法是在WM_PAINT消息中用BeginPaint函数得到hDC,WM_PAINT消息的代码结构一般是:

。if     eax    WM_PAINT   ;eax为uMsg

        invoke   BeginPaint;hWnd;addr stPS

        ;刷新客户区的代码

        invoke   EndPaint;hWnd;addr stPS

        xor      eax;eax

        ret

BeginPaint函数的返回值就是需要刷新区域的hDC。要注意的是:BeginPaint返回的hDC对应的尺寸仅是无效区域,无法用它绘画到这个区域以外的地方去。由于窗口过程每次接收WM_PAINT消息时的无效区域可能都是不同的,所以这个hDC的值仅在WM_PAINT消息中有效,程序不应该保存它并把它用在WM_PAINT消息以外的代码中。基于同样的道理,BeginPaint和EndPaint函数只能用在WM_PAINT消息中,因为只有这时候才存在无效区域。

程序中常常有这种需求,就是在非WM_PAINT消息中主动绘画客户区,由于BeginPaint和EndPaint函数必须在WM_PAINT消息中使用,所以这时必须用另外的方法获取hDC,可以使用以下的方法:

invoke      GetDC;hWnd      ;获取hDC

;返回值是hDC

;绘图代码

invoke      ReleaseDC;hWnd      ;释放hDC

GetDC函数返回的hDC对应窗口的整个客户区,当使用完毕的时候,hDC必须用ReleaseDC函数释放。对于用GetDC获取的hDC,Windows建议使用的范围限于单条消息内,当程序在处理某条消息的时候需要绘画客户区时,可以用GetDC获取hDC,但在消息返回前,必须用ReleaseDC将它释放掉,如果在下一条消息中需要继续用到hDC,那么必须重新用GetDC函数获取。

上面两种方法获取的hDC都是窗口的hDC,如果要操作的是其他的东西,如打印机、位图等,就不能使用BeginPaint或GetDC函数了。当绘图的对象是一个设备的时候,可以用Create DC函数来建立一个DC:

invoke  CreateDC,lpszDriver,lpszDevice,lpszOutput,lpInitData

lpszDriver指向设备名称,如显示设备的设备名是DISPLAY,打印机的设备名一般为WINSPOOL,下面这几句代码建立的DC对应整个屏幕:

szDriver        db      〃DISPLAY〃;0

                。。。

                invoke  CreateDC;addr szDriver;NULL;NULL;NULL

                mov     hDC;eax

当绘图对象是位图的时候,同样需要一个和位图句柄相联系的DC,这时可以用函数CreatepatibleDC来创建一个显示表面仅存在于内存中的DC:

invoke  CreatepatibleDC;hDc

参数中的hDC是用来参考的DC句柄,如果指定的参数是NULL,那么建立的DC将和当前屏幕的设置兼容,为了用CreatepatibleDC建立的DC绘画一个位图,还需要用SelectObject函数将hDC和位图句柄联系起来。

用CreateDC和CreatepatibleDC函数建立的hDC在使用结束以后,必须用DeleteDC函数删除,注意这里不能用ReleaseDC,这个函数是和GetDC配合用的。

用BeginPaint/EndPaint以及GetDC获取的hDC的使用时间不能超出本条消息,与此相比,用CreateDC以及CreatepatibleDC建立的hDC就没有这个限制,可以在任何时刻建立它并且一直使用到不再需要为止。

7。1。3  色彩和坐标

1。 Windows中的色彩

可以表示的颜色总数由颜色深度决定,也就是存储每个像素所用的位数,各种显示设备可以显示的颜色总数可能大不相同,如果设备支持的颜色深度太浅,就会影响到图像的质量,会让人看起来觉得很粗糙和不自然。

一种颜色可以分解成红、绿、蓝三原色,所以可以用红、绿、蓝3个分量的组合来表示各种颜色。

当设备支持的颜色深度少于等于8位时(如8位(256色)、4位(16色)、2位(4色)或1位(2色)),总体位数太少,不足以用来表达3个颜色分量,这时系统建立一个色彩表,像素数据用

返回目录 上一页 下一页 回到顶部 2 2

你可能喜欢的