|
概述 在前面八篇的 Win32asm 教程中,已经初步讲述了消息框、对话框、菜单、资源、GDI 等内容,基本上已经设计到了 Windows 界面的大部分内容,在继续新的 Windows 其他部分的内容如多线程、文件操作、内存操作之前,我先综合前面的内容并加上一些新内容,写上一篇综合篇。 本篇的例子程序是一个复杂形状的窗口,窗口的形状是根据位图自动计算得到的,这也就是在我编写的小闹钟中使用的技术(大家可以到我的软件发布中下载一个看看),由于以前在网上看到的有关特殊形状窗口的例子最多就是画一个圆形,或者几个方块和椭圆结合的形状,没有一篇文章指出如何画出如“唐老鸭”这样一个造型的窗口。本文使用的算法可以自动根据位图的形状计算窗口形状。 在源程序中,很多代码都是前面教程提到的,主要有以下部分:
首先建立一个标准的窗口。(参考窗口一节) 设置窗口为特殊形状。(见下面的程序分析) 在窗口的 WM_PAINT 消息中更新窗口的图片。(参考图形界面一节) 由于窗口没有标题栏,所以在右击窗口时弹出一个菜单。(参考菜单一节) 菜单中有个“关于本程序”项,里面有超联结文本。(参考窗口子类化一节) Windows 里有专门的 API 来实现特殊形状的窗口,步骤是首先建立区域(Region),Region 可以合并,这样一来就可以用几个简单的区域合并出一个复杂的区域,建立、合并区域和设置窗口的 API 主要有以下几条:
CreateRectRgn(Left,Top,Right,Bottom) - 建立矩型区域 CreateEllipticRgn(Left,Top,Right,Bottom) - 建立椭圆区域 CreatePolygonRgn(lpPoints,NumberOfPoints,Mode) - 建立多边形区域,这些API返回区域句柄 CombineRgn(hDest,hSource1,hSource2,CombineMode) - 合并区域 SetWindowRgn(hWnd,hRgn,bRedraw) - 根据区域设置窗口形状 本程序的方法是扫描位图的点,按行设置区域,然后合并到总的区域中。
源程序 - 汇编源文件
以下是代码片段: ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 是否包括调试代码 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DEBUG = 0 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Programmed by 罗云彬, bigluo@telekbird.com.cn ; Website: http://asm.yeah.net ; LuoYunBin's Win32 ASM page (罗云彬的编程乐园) ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 版本信息 ; 特殊形状窗口的演示程序 Ver 1.0 ; 可以根据位图自动设置窗口的形状。 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386 .model flat, stdcall option casemap :none ; case sensitive
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 数据 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc include kernel32.inc include comctl32.inc include comdlg32.inc include shell32.inc include gdi32.inc
includelib user32.lib includelib kernel32.lib includelib comctl32.lib includelib comdlg32.lib includelib shell32.lib includelib gdi32.lib ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Equ 数据 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;************** Equ 数据 ********************************** IDI_MAIN equ 1 ;icon IDC_HANDLE equ 2 ;Cursor ;************** Equ 数据 ********************************** DLG_ABOUT equ 1200 ;dialog - about ID_ABOUT_OK equ 1201 ID_EMAIL equ 1202 ID_HOMEPAGE equ 1203 ;************** Equ 数据 ********************************** IDM_MAIN equ 2000 IDM_ABOUT equ 2001 IDM_EXIT equ 2002 ;************** Equ 数据 ********************************** IDB_0 equ 3000 ;bitmap
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 数据段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .data? hInstance dd ? hWinMain dd ? hIcon dd ? hCursor dd ? hMenu dd ?
hBmpBack dd ? ;background bitmap hDcBack dd ?
;************** 数据段 ************************************ .data
szClassName db 'ShapeWindow',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 代码段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
if DEBUG include Debug.asm endif ;******************************************************************** ; 设置窗口形状为BMP图形形状 ; 参数:窗口句柄,BMP图形句柄 ; 输入BMP图形要求:0,0处颜色为背景色 ;******************************************************************** _SetWindowShape proc hWnd:DWORD,hBitMap:DWORD local @hDC:DWORD,@hBmpDC:DWORD local @stPs:PAINTSTRUCT local @stRect:RECT local @stBmp:BITMAP local @dwX:DWORD,@dwY:DWORD,@dwStartX:DWORD local @hRgn:DWORD,@hRgnTemp:DWORD local @rgbBack:DWORD
invoke GetObject,hBitMap,sizeof BITMAP,addr @stBmp invoke GetWindowRect,hWnd,addr @stRect invoke ShowWindow,hWnd,SW_HIDE invoke MoveWindow,hWnd,@stRect.left,@stRect.top,\ @stBmp.bmWidth,@stBmp.bmHeight,FALSE
invoke GetDC,hWnd mov @hDC,eax invoke CreateCompatibleDC,@hDC mov @hBmpDC,eax invoke SelectObject,@hBmpDC,hBitMap ;*************** 计算窗口形状 *************************************** invoke GetPixel,@hBmpDC,0,0 mov @rgbBack,eax invoke CreateRectRgn,0,0,0,0 mov @hRgn,eax
mov @dwY,0 .while TRUE mov @dwX,0 mov @dwStartX,-1 .while TRUE invoke GetPixel,@hBmpDC,@dwX,@dwY .if @dwStartX == -1 .if eax != @rgbBack mov eax,@dwX mov @dwStartX,eax .endif .else .if eax == @rgbBack mov ecx,@dwY inc ecx invoke CreateRectRgn,@dwStartX,@dwY,@dwX,ecx invoke CombineRgn,@hRgn,@hRgn,eax,RGN_OR mov @dwStartX,-1 .else mov eax,@dwX .if eax == @stBmp.bmWidth inc eax mov ecx,@dwY inc ecx invoke CreateRectRgn,@dwStartX,@dwY,eax,ecx invoke CombineRgn,@hRgn,@hRgn,eax,RGN_OR mov @dwStartX,-1 .endif .endif .endif inc @dwX mov eax,@dwX .break .if eax > @stBmp.bmWidth .endw inc @dwY mov eax,@dwY .break .if eax > @stBmp.bmHeight .endw
invoke SetWindowRgn,hWnd,@hRgn,TRUE ;********** [1] [2] [3] 下一页 |