唐山市网站建设_网站建设公司_定制开发_seo优化
2026/1/3 9:52:44 网站建设 项目流程

在这儿下载本节的所有源程序(74k)。

概述

在前面八篇的 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

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

invoke BitBlt,@hDC,0,0,@stBmp.bmWidth,@stBmp.bmHeight,\

@hBmpDC,0,0,SRCCOPY

invoke DeleteDC,@hBmpDC

invoke ReleaseDC,hWnd,@hDC

invoke InvalidateRect,hWnd,NULL,-1

ret

_SetWindowShape endp

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

; 将窗口移动到屏幕中间

; 参数:窗口句柄

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

_CenterWindow proc hWnd:DWORD

local @stRectDeskTop:RECT,@stRectWin:RECT

local @dwWidth:DWORD,@dwHeight:DWORD

invoke GetWindowRect,hWnd,addr @stRectWin

invoke GetDesktopWindow

mov ebx,eax

invoke GetWindowRect,ebx,addr @stRectDeskTop

mov eax,@stRectWin.bottom

sub eax,@stRectWin.top

mov @dwHeight,eax

mov eax,@stRectWin.right

sub eax,@stRectWin.left

mov @dwWidth,eax

mov ebx,@stRectDeskTop.bottom

sub ebx,@dwHeight

shr ebx,1

mov ecx,@stRectDeskTop.right

sub ecx,@dwWidth

shr ecx,1

invoke MoveWindow,hWnd,ecx,ebx,@dwWidth,@dwHeight,FALSE

ret

_CenterWindow endp

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

include About.asm

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 程序开始

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

start:

call _WinMain

invoke ExitProcess,NULL

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 主窗口程序

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_WinMain proc

local @stWcMain:WNDCLASSEX

local @stMsg:MSG

invoke InitCommonControls

invoke GetModuleHandle,NULL

mov hInstance,eax

invoke LoadIcon,hInstance,IDI_MAIN

mov hIcon,eax

invoke LoadMenu,hInstance,IDM_MAIN

invoke GetSubMenu,eax,0 ;PopUp 菜单要用到子菜单

mov hMenu,eax

;*************** 注册窗口类 *****************************************

invoke LoadCursor,0,IDC_ARROW

mov @stWcMain.hCursor,eax

mov @stWcMain.cbSize,sizeof WNDCLASSEX

mov @stWcMain.hIconSm,0

mov @stWcMain.style,CS_HREDRAW or CS_VREDRAW

mov @stWcMain.lpfnWndProc,offset WndMainProc

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询