友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
依依小说 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

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

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




            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种,它们是3种原始数据进行不同位操作(取反、与、或和异或)的组合,但有些ROP码对应的操作结果实在是太难想像了,比如ROP码0e20746对应的操作是((目标像素 xor 画刷) and 源像素) xor 目标像素),凭这个算式的确比较难以想像最后得到的位图是什么样子的!在实际使用中很多算法组合也并不是那么有用,所以Windows只对15种最常用的ROP码定义了预定义的助记代码, 

如表7。6所示,对于这些ROP码,在程序中可以直接使用助记码,对于表中没有列出的ROP码,可以直接使用16进制数值。

表7。6  块传送函数中使用的ROP码

ROP码
 16进制数值
 新像素点算法
 
BLACKNESS
 00000042h
 全部为0
 
DSTINVERT
 00550009h
 not 目标像素
 
MERGECOPY
 00c000cah
 画刷 and 源像素
 
MERGEPAINT
 00bb0226h
 (not 源像素)or 目标像素
 
NOTSRCCOPY
 00330008h
 not 源像素
 
NOTSRCERASE
 001100a6h
 not(源像素 or 目标像素)
 
PATCOPY
 00f00021h
 画刷
 
PATINVERT
 005a0049h
 画刷 xor 目标像素
 
PATPAINT
 00fb0a09h
 画刷 or (not 源像素)or 目标像素
 
SRCAND
 008800c6h
 源像素 and 目标像素
 
SRCCOPY
 00cc0020h
 源像素
 
SRCERASE
 00440328h
 源像素 and(not 目标像素)
 
SRCINVERT
 00660046h
 源像素 xor 目标像素
 
SRCPAINT
 00ee0086h
 源像素 or 目标像素
 
WHITENESS
 00ff0062h
 全部为1
 

7。4。2  块传送函数

1。 PatBlt函数

PatBlt函数完成的是“图案块传送”的功能,即“Pattern Block Transfer”。使用的方法是:

invoke  PatBlt,hDC,xDest,yDest,dwWidth,dwHeight,dwROP

这个函数将当前画刷的图案拷贝到hDC中以(xDest,yDest)为左上角坐标,dwWidth为宽度,dwHeigth为高度的区域中,传送的方式由dwROP中的ROP码指定。PatBlt函数的功能和矩形填充函数FillRect与InvertRect等是很像的,但它包含了它们的全部功能,如ROP码指定DSTINVERT,那么PatBlt的功能就相当于InvertRect函数;ROP码指定为PATCOPY的时候,PatBlt的功能相当于FillRect函数。

在BmpClock。asm的_CreateBackGround子程序中,当建立背景图片的时候,就是用PATCOPY方式的PatBlt函数用资源中的背景图片填充整个时钟背景的。

在所有的ROP码中,可以用在PatBlt函数中的只有一部分,所有算法中包含源像素的ROP码在PatBlt函数中都不能使用,因为PatBlt函数只涉及当前画刷和目标像素,并没有一个“源像素”,所以对于这个函数来说,表7。6中的ROP码中只有BLACKNESS,WHITENESS,DSTINVERT,PATINVERT和PATCOPY是可用的。

2。 BitBlt函数

PatBlt函数能完成的工作BitBlt函数都能完成,BitBlt是“数据块传送”的意思,即“Bit Block Transfer”。BitBlt函数的用法是:

invoke    BitBlt,hDcDest,xDest,yDest,dwWidth,dwHeigt,

          hDcSrc,xSrc,ySrc,dwROP

这个函数将源hDcSrc中以(xSrc,ySrc)为左上角的一个矩形区域传送到目标hDcDest中以(xDest,yDest)为左上角的地方去,矩形的宽度为dwWidth,高度为dwHeight,当然目标DC中的最后结果是由dwROP中的ROP码定义的源、目标和画刷三者数据的组合。

灵活使用ROP码可以实现很多的功能,比如在一个背景图片上叠加一个非矩形的位图,游戏程序中人物在背景上面的移动就是这样的一个例子。BmpClock程序中也实现了类似的功能——读者可以注意到,程序可以自由更换背景和边框,但是边框是中空的,它相当于以一个不规则的图形叠加在背景上面,图7。10示范了实现的方法。

分析一下BmpClock。asm中的_CreateBackGround子程序就可以发现,程序用到了资源中的Back1。bmp,Mask1。bmp和Circle1。bmp这3个图片(在图7。10中以A,B,C来表示),子程序将3个图片装入内存后,创建了3个DC来存取它们,对应的DC句柄分别放在@hBmpBack,@hBmpMask和@hBmpCircle中。

好了!现在的任务是将图片C中需要的部分(非黑色部分)透明叠放在以图片A形成的背景上,得到时钟背景图片D。继续做准备工作:为图片D建立一个未初始化位图和内存DC,DC句柄存放在hDcBack中。


图7。10  在背景上叠加不规则图形的方法

如图7。10中的步骤1所示,首先,程序用CreatePatternBrush建立以图片A为图案的画刷,用PatBlt函数以这个画刷填充整个图片:

    invoke  CreatePatternBrush;@hBmpBack

    push        eax

    invoke  SelectObject;hDcBack;eax

    invoke  PatBlt;hDcBack;0;0;CLOCK_SIZE;CLOCK_SIZE;PATCOPY

    pop     eax

    invoke  DeleteObject;eax

现在如果直接将图片C拷贝上去,虽然需要的部分是拷贝上去了,但是图片C中的黑色部分也会覆盖全部的背景像素,为了让黑色部分的背景像素保持不变,应该使用or操作,因为黑色的颜色值为0,任何数据和0进行or操作将保持不变,查看ROP码可以发现,SRCPAINT使用的是or操作,所以可以使用SRCPAINT操作码进行BitBlt操作。

但还有个问题:图片C中的非黑色部分如果也用or操作绘画到背景上,那么经过和背景像素的or操作后就不是原来的颜色值了,为了让这部分不变,解决的办法是预先将背景中对应的部分先绘制成黑色,这样对应图片C中的黑色部分将保持背景颜色,而非黑色部分将使用图片C中的像素。遮掩图片B就是这样用的,它是一个黑白两色的图片,黑色部分是图片C中要在背景上“镂空”的部分,在步骤2中,程序使用下列语句将图片B用SRCAND操作码绘制到背景上:

invoke  BitBlt;hDcBack;0;0;CLOCK_SIZE;CLOCK_SIZE;@hDcMask;0;0;SRCAND

查表7。6可以发现,SRCAND进行源像素和目标像素的and操作,任何数和1进行and将保持不变,和0进行and将变成0,这样背景中对应图片B中的白色部分将保持不变,对应图片B中的黑色部分将被“镂空”。

接下来就是最后的步骤3了:

invoke  BitBlt;hDcBack;0;0;CLOCK_SIZE;CLOCK_SIZE;@hDcCircle;0;0;SRCPAINT



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


第7章 图形操作


7。4 块传送操作(2)

    
程序用SRCPAINT操作码将图片C和已经镂空的背景进行or操作,得到的结果就是将由遮掩图片B指定的图片C中的不规则区域画到了背景上面。

为了简化起见,BmpClock程序中的遮掩图片是预先设计好的,实际使用中也可以通过扫描源位图中的像素位,找出背景颜色并动态生成一个遮掩位图,虽然这样可能对速度有一些影响,但灵活性要高得多。

在游戏程序中,将一个不规则的图形如人或物体等图形叠加到背景上面使用的就是这样的技术。

3。 MaskBlt函数

MaskBlt函数允许在一个图片中对不同的部分以不同的ROP码进行操作,它的语法是:

    invoke  MaskBlt,hDcDest,xDest,yDest,dwWidth,dwHeigt,

            hDcSrc,xSrc,ySrc,hMaskBmp,xMask,yMask,dwROP

它和BitBlt的不同之处是多了一个遮掩图片句柄hMaskBmp(注意:是位图句柄而不是DC句柄)以及hMaskBmp的开始坐标。

MaskBlt函数同样是将hDcSrc以(xSrc,ySrc)为左上角的矩形区域以指定ROP码操作方式传送到hDcDest中以(xDest,yDest)为左上角的矩形区域中,矩形的宽度和高度由dwWidth和dwHeight指定,函数的特殊之处是可以指定两个ROP码,传送时使用哪个ROP码要参考遮掩图片,参考的位置从遮掩图片的(xMask,yMask)坐标开始。

hMaskBmp指定了一幅黑白位图,如果位图中
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!