news 2026/4/15 7:36:26

汇编语言全接触-26.启动画面

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
汇编语言全接触-26.启动画面

上一章我们学习了位图的使用.在这一章我们要用上帝赋予我们的创造力来融会贯通上一章我们学到的知识.那就是研究如何用位图来创建启动画面. 你可以在这里下载示范: the example.

理论

首先,我们先要搞清楚什么是启动画面.举个简单的例子:我们启动某些作的专业一点的程序时(比如Netscape,Adobe Acrobat等)会先跳出一个启动画面.上面通常有一些版权信息,版本号等.与此同时,程序后台正做着一些程序的加载或初始化工作.这个启动画面有别于一般的窗口.它没有标题栏,没有系统菜单,也没有边框.只有一张位图在屏幕上显示一会儿,然后消失 .在这一章我们来试试自己做一个.

第一步你可能会想到把要显示的位图包含到资源文件中去.但是这样做有一个缺点.你的程序只在启动的时候显示这张位图,可是它却至始至终存在于你的内存中,直到你把程序关掉.这不能不说是对内存的极大浪费.好办法是:创建一个"资源"DLL(动态连接库)来包含位图和它独特的显示代码.这样,你就可以在想显示启动画面的时候加载他,用完了就卸载它.所以,我们的程序需要2个模块:主程序和启动画面DLL.我们要把位图放到这个DLL的资源中去.

基本步骤如下:

把位图作为一个位图资源放到DLL中去.

主程序调用 LoadLibrary 把 dll 加载到内存中去.

DLL 被调用后,它会建立一个定时器用于管理启动画面显示的时间.然后,注册并创建一个没有 标题和边框的窗口.同时在窗口的客户区显示位图.

等启动画面的显示时间长度到达你预先的设定值,启动画面消失,控制权回到主程序手中.

主程序调用 FreeLibrary 从内存中卸载 DLL .然后,做它该做的事去.

下面我们来研究细节部分

加载/卸载 DLL

你可以用 LoadLibrary 灵活的加载一个 DLL ,它的格式如下:

LoadLibrary proto lpDLLName:DWORD

它只有一个参数: 你想要加载的 DLL 的名称所在的地址.调用成功返回指向该DLL模块的句柄,反之返回NULL.

要卸载 DLL, 则调用 FreeLibrary:

FreeLibrary proto hLib:DWORD

它也只有一个参数: 你想要卸载的 DLL 模块的句柄(通常就是上面那个函数返回的啦).

怎样使用定时器

首先, 你要用 SetTimer 创建一个定时器:

SetTimer proto hWnd:DWORD, TimerID:DWORD, uElapse:DWORD, lpTimerFunc:DWORD

hWnd接受这个定时器消息的窗口的句柄.如果,你的定时器不需要窗口接受它的消息,你也可以 用NULL作为参数

TimerID定时器的 ID 值. 由你自己定义.

uElapse 定时器定的时间.以ms(千分之一秒)为单位.

lpTimerFunc 处理该定时器消息的函数所在的地址.如果你用NULL作为该参数,那么定时器的消息会被送给 hWnd 参数所指定的窗口.

SetTimer 如果成功则返回定时器的 ID 否则返回 NULL. 所以最好不要把定时器的ID设为0(Pheadnius:NULL代表0, 记得吗?).

你可以用2种方法创建定时器:

如果你有一个窗口并且定时器把消息传给这个窗口.那么你需要把所有的4个参数都传送给 Settimer 函数 (lpTimerFunc参数必须为NULL).

如果你没有窗口或者你不想让窗口处理定时器的消息,那么你必须在窗口句柄中传送一个NULL.同时你要指定用于处理定时器消息的函数的地址.

在这个例子中我们要使用第一种方法.

当你设定的时间到了, 与定时器相连的窗口会收到 WM_TIMER 消息.例如,你指定 uElapse 的值为 1000, 你的窗口每过一秒都会收到 WM_TIMER 消息.

等到你再也不需要这个定时器了,就用 KillTimer 来去除定时器.

KillTimer proto hWnd:DWORD, TimerID:DWORD

例子:

;-----------------------------------------------------------------------

; 主程序

;-----------------------------------------------------------------------

.386

.model flat,stdcall

option casemap:none

include \masm32\include\windows.inc

include \masm32\include\user32.inc

include \masm32\include\kernel32.inc

includelib \masm32\lib\user32.lib

includelib \masm32\lib\kernel32.lib

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

.data

ClassName db "SplashDemoWinClass",0

AppName db "Splash Screen Example",0

Libname db "splash.dll",0

.data?

hInstance HINSTANCE ?

CommandLine LPSTR ?

.code

start:

invoke LoadLibrary,addr Libname

.if eax!=NULL

invoke FreeLibrary,eax

.endif

invoke GetModuleHandle, NULL

mov hInstance,eax

invoke GetCommandLine

mov CommandLine,eax

invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT

invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD

LOCAL wc:WNDCLASSEX

LOCAL msg:MSG

LOCAL hwnd:HWND

mov wc.cbSize,SIZEOF WNDCLASSEX

mov wc.style, CS_HREDRAW or CS_VREDRAW

mov wc.lpfnWndProc, OFFSET WndProc

mov wc.cbClsExtra,NULL

mov wc.cbWndExtra,NULL

push hInstance

pop wc.hInstance

mov wc.hbrBackground,COLOR_WINDOW+1

mov wc.lpszMenuName,NULL

mov wc.lpszClassName,OFFSET ClassName

invoke LoadIcon,NULL,IDI_APPLICATION

mov wc.hIcon,eax

mov wc.hIconSm,eax

invoke LoadCursor,NULL,IDC_ARROW

mov wc.hCursor,eax

invoke RegisterClassEx, addr wc

INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\

WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\

CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\

hInst,NULL

mov hwnd,eax

invoke ShowWindow, hwnd,SW_SHOWNORMAL

invoke UpdateWindow, hwnd

.while TRUE

invoke GetMessage, ADDR msg,NULL,0,0

.break .if (!eax)

invoke TranslateMessage, ADDR msg

invoke DispatchMessage, ADDR msg

.endw

mov eax,msg.wParam

ret

WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

.IF uMsg==WM_DESTROY

invoke PostQuitMessage,NULL

.ELSE

invoke DefWindowProc,hWnd,uMsg,wParam,lParam

ret

.ENDIF

xor eax,eax

ret

WndProc endp

end start

;--------------------------------------------------------------------

; 位图 DLL

;--------------------------------------------------------------------

.386

.model flat, stdcall

include \masm32\include\windows.inc

include \masm32\include\user32.inc

include \masm32\include\kernel32.inc

include \masm32\include\gdi32.inc

includelib \masm32\lib\user32.lib

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\gdi32.lib

.data

BitmapName db "MySplashBMP",0

ClassName db "SplashWndClass",0

hBitMap dd 0

TimerID dd 0

.data

hInstance dd ?

.code

DllEntry proc hInst:DWORD, reason:DWORD, reserved1:DWORD

.if reason==DLL_PROCESS_ATTACH ; When the dll is loaded

push hInst

pop hInstance

call ShowBitMap

.endif

mov eax,TRUE

ret

DllEntry Endp

ShowBitMap proc

LOCAL wc:WNDCLASSEX

LOCAL msg:MSG

LOCAL hwnd:HWND

mov wc.cbSize,SIZEOF WNDCLASSEX

mov wc.style, CS_HREDRAW or CS_VREDRAW

mov wc.lpfnWndProc, OFFSET WndProc

mov wc.cbClsExtra,NULL

mov wc.cbWndExtra,NULL

push hInstance

pop wc.hInstance

mov wc.hbrBackground,COLOR_WINDOW+1

mov wc.lpszMenuName,NULL

mov wc.lpszClassName,OFFSET ClassName

invoke LoadIcon,NULL,IDI_APPLICATION

mov wc.hIcon,eax

mov wc.hIconSm,0

invoke LoadCursor,NULL,IDC_ARROW

mov wc.hCursor,eax

invoke RegisterClassEx, addr wc

INVOKE CreateWindowEx,NULL,ADDR ClassName,NULL,\

WS_POPUP,CW_USEDEFAULT,\

CW_USEDEFAULT,250,250,NULL,NULL,\

hInstance,NULL

mov hwnd,eax

INVOKE ShowWindow, hwnd,SW_SHOWNORMAL

.WHILE TRUE

INVOKE GetMessage, ADDR msg,NULL,0,0

.BREAK .IF (!eax)

INVOKE TranslateMessage, ADDR msg

INVOKE DispatchMessage, ADDR msg

.ENDW

mov eax,msg.wParam

ret

ShowBitMap endp

WndProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

LOCAL ps:PAINTSTRUCT

LOCAL hdc:HDC

LOCAL hMemoryDC:HDC

LOCAL hOldBmp:DWORD

LOCAL bitmap:BITMAP

LOCAL DlgHeight:DWORD

LOCAL DlgWidth:DWORD

LOCAL DlgRect:RECT

LOCAL DesktopRect:RECT

.if uMsg==WM_DESTROY

.if hBitMap!=0

invoke DeleteObject,hBitMap

.endif

invoke PostQuitMessage,NULL

.elseif uMsg==WM_CREATE

invoke GetWindowRect,hWnd,addr DlgRect

invoke GetDesktopWindow

mov ecx,eax

invoke GetWindowRect,ecx,addr DesktopRect

push 0

mov eax,DlgRect.bottom

sub eax,DlgRect.top

mov DlgHeight,eax

push eax

mov eax,DlgRect.right

sub eax,DlgRect.left

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 2:45:21

随机抽奖算法实现与对比:聚焦洗牌算法(Fisher-Yates)

期末课程设计中,我和团队成员共同完成了 “随机抽奖算法实现与比较” 的课题。本次设计的核心目标是模拟实际抽奖场景,从指定号码范围(min_num 到 max_num)中抽取 k 个不重复的中奖号码,并通过实现四种不同算法&#x…

作者头像 李华
网站建设 2026/4/9 21:49:18

【Hadoop+Spark+python毕设】物联网网络安全威胁数据分析系统、计算机毕业设计、包括数据爬取、数据分析、数据可视化、Hadoop、实战教学

🎓 作者:计算机毕设小月哥 | 软件开发专家 🖥️ 简介:8年计算机软件程序开发经验。精通Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等技术栈。 🛠️ 专业服务 🛠️ 需求定制化开发源码提…

作者头像 李华
网站建设 2026/4/15 6:36:08

Springboot连锁药店进销存业务系统98i85(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能:员工,供应商,药品信息,药品采购,进货出库,药品销售,退货入库,药品报损,药品销毁开题报告内容基于SpringBoot的连锁药店进销存业务系统开题报告一、选题背景与意义1.1 行业现状与痛点随着医疗行业的快速发展和人们对健康需求的日益增加&…

作者头像 李华
网站建设 2026/4/10 20:45:13

智能测试指标动态权重分配研究

随着人工智能与机器学习技术在软件测试领域的深度渗透,传统静态权重分配模式已难以适应瞬息万变的测试环境。本文基于2025年行业实践数据,提出以动态权重分配为核心的新型测试评估体系,通过构建具备自适应能力的指标权重矩阵,有效…

作者头像 李华
网站建设 2026/4/10 6:29:35

std::promise 重难点

std::promise 重难点全拆解 std::promise 是 C11 异步编程的核心组件,但其难点不在于语法本身,而在于状态管理、生命周期控制、异常传递等“隐性规则”——踩中任何一个都可能导致程序崩溃或逻辑异常。本文用“专业底层逻辑通俗比喻分步实操”的方式&…

作者头像 李华