八喜电子书 > 经管其他电子书 > windows环境下32位汇编语言程序设计 >

第39部分

windows环境下32位汇编语言程序设计-第39部分

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

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



多次调用AppendMenu创建需要的菜单项(相关内容见第5章的“菜单”一节)。然后,程序用CreateEllipticRgn建立一个区域,并用SetWindowRgn函数把窗口设置成圆形,这两个函数在本章的最后一节介绍。接下来,程序用SetWindowPos函数把窗口设置为“总在最前面”。在WM_CREATE消息的最后,程序调用_CreateBackGround和_CreateClockPic创建背景位图和时钟位图,这是这一节中要详细介绍的内容。和前面简单的时钟程序类似,本程序也建立了一个周期为1s的定时器用来刷新屏幕。

在选择菜单后的WM_MAND消息中,程序调用_DeleteBackGround子程序先删除原有的位图,再调用_CreateBackGround和_CreateClockPic子程序产生新的背景位图和时钟位图,最后调用InvalidateRect函数产生WM_PAINT消息重新绘画客户区。

程序有个特殊之处是对WM_LBUTTONDOWN消息的处理,由于建立的窗口没有标题栏,所以无法用拖动标题栏的方法移动窗口,为了在窗口客户区拖动鼠标就能够移动窗口,必须欺骗Windows,让它认为是在拖动标题栏,所以在WM_LBUTTONDOWN消息中,程序发送位置为HTCAPTION的WM_NCLBUTTONDOWN消息,这样就相当于告诉Windows用户按下的是标题栏。头尾处的两个SetCursor函数是为了按下鼠标时让光标变成一个抓住东西的手的形状。

整个程序的结构采用图7。1中的B结构,也就是说窗口客户区的绘画代码和产生时钟位图的代码是分开的,程序中建立了两个位图当做缓冲数据,第一个位图是背景位图,在_CreateBackGround子程序中建立,只有在程序初始化以及在菜单中选择了不同的背景和边框后才需要调用这个子程序,以便建立新的背景图片;第二个位图是要输出到屏幕的时钟位图,它在_CreateClockPic子程序中建立,时钟位图是通过将背景位图拷贝过来,再根据当前时间画上指针得到的,程序在WM_TIMER消息中每秒重画一次新的时钟图片,并用InvalidateRect函数产生一个WM_PAINT消息将这个位图拷贝到屏幕上,当其他原因产生WM_PAINT消息时,程序并不从头开始产生背景位图和时钟位图等图片,而是直接从时钟图片中拷贝数据到屏幕上。

好了,接下来继续分析_CreateBackGround和_CreateClockPic子程序是如何对位图进行处理的。

7。3。2  创建和使用位图

所有绘图函数的操作对象都是“设备环境”,对位图操作也不例外。为了对位图使用GDI函数,需要使用CreatepatibleDC函数为位图建立一个DC,然后使用SelectObject函数将位图选入这个DC中,这样,所有对这个DC的绘图操作实际上就是在操作这个位图。每一个需要操作的位图都需要单独为它创建一个DC。

程序中常常使用在资源中预定义的位图,但也有使用未初始化的位图的情况,如例子程序的背景位图和时钟位图一开始就是未初始化的,它们是程序开始运行后才被创建的。

为了建立一个未初始化的位图,可以使用以下的函数:

    invoke  CreatepatibleBitmap,hDC,dwWidth,dwHeight

    mov hBitmap1;eax        ;方法1

    invoke  CreateBitmap,dwWidth,dwHeight,dwPlanes,dwBitsPerPel,NULL

    mov hBitmap2;eax        ;方法2



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


第7章 图形操作


7。3 创建和使用位图(5)

    
创建一个位图需要的参数是高度、宽度以及颜色深度,要创建位图必须得知这些参数。使用CreatepatibleBitmap创建位图的时候,参数中有一个hDC,这是个参考hDC,也就是说,新位图的颜色深度和hDC对应的“设备环境”的颜色深度相同(注意:有个hDC参数的意思并不是将创建的位图选入这个hDC中)。CreateBitmap函数则直接在参数dwPlanes和dwBitsPerPel中指定了颜色深度。两个函数的dwWidth和dwHeight参数指定创建的位图的宽度和高度。

在例子程序的_CreateBackGround子程序中,为了建立背景图片和时钟图片,需要建立两个未初始化的位图和操作它们的DC,所以程序一开始用GetDC函数获取主窗口的hDC来当做参考DC,然后用CreatepatibleDC函数建立了两个DC(句柄放在全局变量hDcBack和hDcClock中),并用CreatepatibleBitmap建立了两个位图(句柄放入hBmpBack和hBmpClock中),接下来用SelectObject将这两个位图选入新建的hDC中。

创建背景图片的过程中还要用到资源中的背景图片、边框图片和边框的遮掩图片,对于这些图片,程序用LoadBitmap函数装入,并使用CreatepatibleDC为每个图片建立一个DC。

对于不再使用的位图,要用DeleteObject函数将它们删除。所以在子程序的最后,使用DeleteObject函数将临时使用的位图句柄删除,并使用DeleteDC将操作这些位图的hDC删除。

操作未初始化位图需要用到CreatepatibleDC和CreatepatibleBitmap函数,初学者常犯的错误是用CreatepatibleDC返回的hDC当做CreatepatibleBitmap函数的参考hDC,这样的结果是建立的位图是单色的,正确的做法是两个函数的参考hDC都使用窗口客户区的hDC。

7。3。3  使用设备无关位图

设备无关位图简称为DIB,这在5。3。1小节中已经有所介绍。DIB一般是存放在磁盘上的以bmp为扩展名的位图文件,使用DIB的关键是如何将DIB中的数据转化为一个内存中的位图并返回一个位图句柄。

bmp文件的文件结构是这样定义的:文件的开始是一个BITMAPFILEHEADER结构,这个结构定义如下:

BITMAPFILEHEADER STRUCT

  bfType           WORD       ?    ;文件标识,必须是“BM”

  bfSize           DWORD     ?    ;文件长度

  bfReserved1      WORD      ?    ;0

  bfReserved2      WORD      ?    ;0

  bfOffBits        DWORD     ?    ;位图像素数据在文件中的起始位置

BITMAPFILEHEADER   ENDS

BITMAPFILEHEADER结构的后面要么是BITMAPCOREHEADER结构,要么是BITMAPINFOHEADER结构和索引色表,这两种结构的定义如下:

BITMAPCOREHEADER STRUCT

  bcSize            DWORD     ?    ;本结构长度

  bcWidth          WORD      ?    ;位图宽度

  bcHeight         WORD      ?    ;位图高度

  bcPlanes          WORD      ?    ;位图的色平面数

  bcBitCount        WORD      ?    ;位图的颜色深度

BITMAPCOREHEADER   ENDS

 

BITMAPINFOHEADER STRUCT

  bcSize            DWORD     ?    ;本结构长度

  bcWidth          WORD      ?    ;位图宽度

  bcHeight          WORD      ?    ;位图高度

  bcPlanes         WORD      ?    ;位图的色平面数

  bcBitCount       WORD      ?    ;位图的颜色深度

  bipression    DWORD     ?    ;位图的压缩方式

  biSizeImage      DWORD     ?    ;图形尺寸

  biXPelsPerMeter  DWORD     ?    ;图形x方向分辨率,单位是像素/米

  biYPelsPerMeter  DWORD     ?    ;图形y方向分辨率,单位是像素/米

  biClrUsed        DWORD     ?

  biClrImportant   DWORD     ?

BITMAPINFOHEADER   ENDS

这两个数据结构主要包含了位图的一些参数,在这些数据结构的后面,就是位图的像素数据了,整个bmp文件就由这3部分组成。

要使用DIB,可以首先将整个文件读到内存中,然后从这些数据结构中得知位图的各种参数,最后使用SetDIBitsToDevice函数将位图数据复制到一个hDC中,如果这个hDC对应一个未初始化的位图,那么就相当于得到了包含磁盘bmp位图数据的位图句柄,并且可以在任何地方使用它。当然,在这以后可以将读入文件数据的内存释放掉。

SetDIBitsToDevice函数的用法是:

invoke  SetDIBitsToDevice;hDC;xDest;yDest;

            dwWidth;dwHeight;xSrc;ySrc;uStartScan;cScanLines;

            lpvBits;lpbmi;fuColorUse

hDC是目的DC的句柄,xDest和yDest指定了位图复制到hDC的左上角位置,dwWidth和dwHeight指定了要复制的宽度和高度,xSrc和ySrc指定DIB中要复制的左上角位置,uStartScan和cScanLines指定开始复制的扫描线和要复制的扫描线数,最后,lpvBits指向DIB中的像素数据部分,lpbmi指向DIB中的BITMAPINFO或BITMAPCOREINFO结构,fuColorUse指定了DIB中数据的类型,用DIB_RGB_COLORS表示数据是RGB类型的。

子程序_CreateDIBitmap分析一个DIB文件的参数并返回包含整个DIB位图数据的位图句柄,读者可以在任何地方使用这个位图句柄。子程序的输入参数_hWnd用来获取参考hDC的窗口句柄,_lpFileData是将DIB文件整个读入内存后的内存指针。代码如下:

_CreateDIBitmap      proc   _hWnd;_lpFileData

            local    @lpBitmapInfo;@lpBitmapBits

            local    @dwWidth;@dwHeight

            local    @hDc;@hBitmap

 

            pushad

            mov      @hBitmap;0

            mov      esi;_lpFileData

            mov      eax;BITMAPFILEHEADER。bfOffBits 'esi'

            add      eax;esi

            mov      @lpBitmapBits;eax

            add      esi;sizeof BITMAPFILEHEADER

            mov      @lpBitmapInfo;esi

            。if      BITMAPINFO。bmiHeader。biSize 'esi'  sizeof BITMAPCOREHEADER

                     movzx  eax;BITMAPCOREHEADER。bcWidth 'esi'

                     movzx  ebx;BITMAPCOREHEADER。bcHeight 'esi'

            。else

                     mov     eax;BITMAPINFOHEADER。biWidth 'esi'

                     mov     ebx;BITMAPINFOHEADER。biHeight 'esi'

            。endif

            mov      @dwWidth;eax

            mov      @dwHeight;ebx

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

; 建立空的 Bitmap Object

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

            invoke   GetDC;_hWnd

            push     eax

            invoke   CreatepatibleDC;eax

            mov      @hDc;eax

            pop      eax

            push     eax

            invoke   CreatepatibleBitmap;eax;@dwWidth;@dwHeight

            mov      @hBitmap;eax

            invoke   SelectObject;@hDc;@hBitmap

            pop      eax

            invoke   ReleaseDC;hWinMain;eax

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

; 将文件内容设置到建立的 Bitmap 中

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

            invoke   SetDIBitsToDevice;@hDc;0;0;@dwWidth;@dwHeight;

                     0;0;0;@dwHeight;

                     @lpBitmapBits;@lpBitmapInfo;DIB_RGB_COLORS

            。if      eax  0

                     invoke DeleteObject;@hBitmap

                     mov @hBitmap;0

            。endif

            invoke   DeleteDC;@hDc

            popad

            mov      eax;@hBitmap

            ret

 

_CreateDIBitmap      endp

_CreateDIBitmap子程序首先分析DIB文件的数据,确定BITMAPFILEHEADER后面的数据结构是BITMAPINFO还是BITMAPCOREINFO,并从结构中获取位图的高度和宽度,然后建立一个未初始化的位图,并用SetDIBitsToDevice函数将位图数据拷贝到这个位图中,最后将位图句柄返回以供后面使用。



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


第7章 图形操作


7。4 块传送操作(1)

    
除了7。2小节中的绘图函数,块传送函数也是重要的图形操作函数。块传送指把源位置中的数据块按照指定的方式传送到目的位置中。把内存中的位图复制到窗口客户区以及在不同的DC中复制图形数据都要用到块传送操作,块传送完成的工作就相当于图形之间的拷贝工作。块传送函数有PatBlt,BitBlt,MaskBlt,PlgBlt,TransparentBlt和StretchBlt等。

7。4。1  块传送方式

与7。2。4小节中介绍的绘图函数的ROP操作类似,块传送函数也是可以用ROP码来定义的传送方式,但块传送函数的ROP码定义不同于7。2。4小节中的ROP码,因为这里涉及的操作对象更多。

块传送的ROP码是一个32位的整数,对应的操作涉及3种原始数据:源像素、目标像素和画刷,块传送操作的结果是目标像素的数据被3种原始数据的计算结果替换掉。

并不是每一种ROP码都要用到全部3种原始数据,有的甚至连1种也用不到,例如全黑或者全白的ROP码。块传送函数使用的ROP码总共有256种,它们

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

你可能喜欢的