news 2026/1/14 10:36:38

汇编语言全接触-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进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/19 17:55:49

本地部署DeepSeek

ollama终端的方式部署参考:ollama本地部署 智谱API Key获取 LM Studio 它是模型的托管平台,可以把模型加载后,作为服务器向外提供服务器,本身也具有简单的对话框可以聊天。 :https://lmstudio.ai/ 在左下角改为开发者…

作者头像 李华
网站建设 2025/12/14 20:33:19

JavaWeb企业级开发---JavaScript

记录在听黑马课的时候的笔记以及课堂上练习的代码,文章图源于我在听课的时候所截的屏,所以有些不清晰,请见谅。下面是课程链接,可点击自行跳转。 【黑马程序员JavaWeb开发教程,实现javaweb企业开发全流程(…

作者头像 李华
网站建设 2025/12/14 20:31:40

微信小程序_WXML

图片&#xff1a;等比例填充&#xff08;头像&#xff09;&#xff1a;mode“aspectFill”<image src"{{userInfo ? userInfo.avatarUrl :/images/1.png}}" mode"aspectFill"></image>

作者头像 李华
网站建设 2025/12/14 20:30:49

Springboot连锁家政保洁管理系统03zmn(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能&#xff1a;分店管理员,用户,保洁员,通知信息,独立服务,团队服务,独立服务信息,团队服务信息,独立服务订单,团队服务订单,团队派单,完成订单,独立服务取消,团队服务取消开题报告内容基于SpringBoot的连锁家政保洁管理系统开题报告一、研究背景与意义研…

作者头像 李华
网站建设 2025/12/14 20:29:15

Redis原理篇-Dict的rehash

** 不管是扩容还是收缩&#xff0c;必定会创建新的哈希表&#xff0c;导致哈希表的size和sizemask变化&#xff0c;而key的查询与sizemask有关。因此必须对哈希表中的每一个key重新计算索引&#xff0c;插入新的哈希表&#xff0c;这个过程称为rehash。过程是这样的&#xff1a…

作者头像 李华
网站建设 2026/1/9 0:07:33

计算机考研408【计算机网络】核心知识点总结

计算机网络作为考研408的重要组成部分&#xff0c;占总分约25分&#xff0c;由选择题和综合应用题构成。掌握计算机网络的基本概念、原理和方法是备考的关键 &#xff0c;尤其要理解OSI参考模型与TCP/IP模型的对应关系&#xff0c;以及各层协议的工作原理。本文将系统梳理计算机…

作者头像 李华