当前位置: 首页 > news >正文

汇编语言全接触-65.Win32汇编教程九

在这儿下载本节的所有源程序(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

http://www.jsqmd.com/news/186315/

相关文章:

  • NumPy 可视化教程
  • 汇编语言全接触-66.Win32汇编教程十
  • 边缘AI推理任务如何稳定运行?基于KubeEdge的任务弹性伸缩设计全公开
  • batch_size对训练稳定性的影响:lora-scripts实测数据
  • 百度搜索优化策略:让lora-scripts相关内容更容易被发现
  • ESP32 FreeRTOS (day1)入门教程 (ESP-IDF版):从超级循环到多任务的系统化思维
  • Java如何实现毫秒级工业传感器校准(仅限高级工程师掌握的技术)
  • 2025年外用贴敷膏厂家直销口碑排行,这份榜单值得收藏,外用理疗贴/定制化贴敷膏/透皮贴敷/经皮给药贴/保健贴敷制剂外用贴敷膏公司排行 - 品牌推荐师
  • 如何在Spring项目中集成多语言JavaDoc?,一线大厂实践揭秘
  • Redis缓存机制优化lora-scripts频繁读取的小文件
  • 百考通AI问卷设计的“智能设计师”,让调研需求一键变专业问卷
  • 为什么90%的Java系统在跨境支付中加密失败?这4个坑你一定要避开
  • 【独家解析】阿里云/腾讯云环境下Java Serverless异步调用差异对比
  • 使用lora-scripts训练科幻实验室场景图:完整流程演示
  • 掌握Java Vector API的3个黄金法则(x64 SIMD优化内幕曝光)
  • 深度测评9个AI论文软件,研究生高效写作必备!
  • STM32调试环境搭建:IAR安装从零实现教程
  • 从数据预处理到权重导出:深入解读lora-scripts自动化流程
  • 为什么你的Java程序还没用上x64向量API?错过后悔十年
  • lora-scripts批量训练多个LoRA模型的工程化方案设计
  • 快速搭建客服对话系统:基于lora-scripts的LLM话术微调
  • 营销文案自动生成不再是梦:用lora-scripts训练话术定制LoRA
  • CVE-2025-14733现实版漏洞检查器(非利用工具)
  • Bilibili UP主推荐:高质量lora-scripts教学视频合集
  • STM32 JFlash下载程序步骤操作指南
  • 降低图片分辨率以适应显存限制:实用且有效的方法
  • 方言语音识别微调方案:lora-scripts小样本训练实践
  • Keil使用教程:超详细版IDE界面功能与工具栏说明
  • emuelec模拟器稳定性增强:深度剖析内核补丁应用
  • Java工程师必备:跨境支付数据加密的7个最佳实践(含代码模板)