📄 lion-tut-c26.htm
字号:
<b>
mov hMemoryDC,eax </b> <br>
<b>
invoke SelectObject,eax,hBitMap </b> <br>
<b>
mov hOldBmp,eax </b> <br>
<b>
invoke GetObject,hBitMap,sizeof BITMAP,addr bitmap </b> <br>
<b>
invoke StretchBlt,hdc,0,0,250,250,\ </b> <br>
<b>
hMemoryDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY </b> <br>
<b>
invoke SelectObject,hMemoryDC,hOldBmp </b> <br>
<b>
invoke DeleteDC,hMemoryDC </b> <br>
<b>
invoke EndPaint,hWnd,addr ps </b> <br>
<b> .elseif uMsg==WM_LBUTTONDOWN </b>
<br>
<b>
invoke DestroyWindow,hWnd </b> <br>
.else <br>
invoke DefWindowProc,hWnd,uMsg,wParam,lParam <br>
ret <br>
.endif <br>
xor eax,eax <br>
ret <br>
WndProc endp
<p> End DllEntry
<h3> 分析:</h3>
我们首先要再主程序中检验这段代码.
<blockquote><b> invoke LoadLibrary,addr Libname </b> <br>
<b> .if eax!=NULL </b> <br>
<b> invoke FreeLibrary,eax </b> <br>
<b> .endif </b></blockquote>
我们调用 LoadLibrary 读入名称为 "splash.dll" 的 DLL. 然后, 用 FreeLibrary 卸载. 一直到 DLL 完成初始化, LoadLibrary才会返回.<br>
主程序的任务到此为止. 更有趣的部分再 DLL里.
<p> .if reason==DLL_PROCESS_ATTACH ; When the dll is loaded
<br>
<b> push hInst </b> <br>
<b> pop hInstance </b> <br>
<b> call ShowBitMap </b>
<p>DLL 被加载后, Windows 调用它的有 DLL_PROCESS_ATTACH 标记的入口函数. 我们借这个机会显示启动画面. 首先,我们
保存 DLL 事例的句柄以供将来使用. 然后, 调用一个叫 ShowBitMap 的函数进行真正的工作. ShowBitMap 注册一个窗口,
创建这个窗口和显示它.就像我们以前创建窗口一样. 有趣的是这个 CreateWindowEx 调用:
<p> INVOKE CreateWindowEx,NULL,ADDR
ClassName,NULL,\ <br>
<b>WS_POPUP</b>,CW_USEDEFAULT,\
<br>
CW_USEDEFAULT,250,250,NULL,NULL,\
<br>
hInstance,NULL
<p>注意, 这里的窗口风格仅仅使用了 WS_POPUP . 所以窗口即没有标题栏,也没有边界. 我们同时也限定窗口的宽高为
250x250个像素.<br>
现在窗口创建好了. 在 WM_CREATE 的消息处理代码里我们把这个窗口移到屏幕的中央.代码如下:
<p><b>
invoke GetWindowRect,hWnd,addr DlgRect </b> <br>
<b>
invoke GetDesktopWindow </b> <br>
<b>
mov ecx,eax </b> <br>
<b>
invoke GetWindowRect,ecx,addr DesktopRect </b> <br>
<b>
push 0 </b> <br>
<b>
mov eax,DlgRect.bottom </b> <br>
<b>
sub eax,DlgRect.top </b> <br>
<b>
mov DlgHeight,eax </b> <br>
<b>
push eax </b> <br>
<b>
mov eax,DlgRect.right </b> <br>
<b>
sub eax,DlgRect.left </b> <br>
<b>
mov DlgWidth,eax </b> <br>
<b>
push eax </b> <br>
<b>
mov eax,DesktopRect.bottom </b> <br>
<b>
sub eax,DlgHeight </b> <br>
<b>
shr eax,1 </b> <br>
<b>
push eax </b> <br>
<b>
mov eax,DesktopRect.right </b> <br>
<b>
sub eax,DlgWidth </b> <br>
<b>
shr eax,1 </b> <br>
<b>
push eax </b> <br>
<b>
push hWnd </b> <br>
<b>
call MoveWindow </b>
<p>它先找到桌面和窗口的大小. 然后,计算出一个窗口左上角的坐标. 使这个窗口能位于屏幕中央.
<p><b>
invoke LoadBitmap,hInstance,addr BitmapName </b> <br>
<b>
mov hBitMap,eax </b> <br>
<b>
invoke SetTimer,hWnd,1,2000,NULL </b> <br>
<b>
mov TimerID,eax </b>
<p>下一步,它用 LoadBitmap 从资源中读入位图并且创建一个定时器.定时器的 ID 为 1 时间间隔为 2 秒. 定时器
将每 2 秒 向窗口发送 WM_TIMER 消息.
<p> .elseif uMsg==WM_PAINT
<br>
<b>
invoke BeginPaint,hWnd,addr ps </b> <br>
<b>
mov hdc,eax </b> <br>
<b>
invoke CreateCompatibleDC,hdc </b> <br>
<b>
mov hMemoryDC,eax </b> <br>
<b>
invoke SelectObject,eax,hBitMap </b> <br>
<b>
mov hOldBmp,eax </b> <br>
<b>
invoke GetObject,hBitMap,sizeof BITMAP,addr bitmap </b> <br>
<b>
invoke StretchBlt,hdc,0,0,250,250,\ </b> <br>
<b>
hMemoryDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY </b> <br>
<b>
invoke SelectObject,hMemoryDC,hOldBmp </b> <br>
<b>
invoke DeleteDC,hMemoryDC </b> <br>
<b>
invoke EndPaint,hWnd,addr ps </b>
<p>当窗口收到 WM_PAINT 消息, 它创建一个内存DC(Pheadnius:还记得DC吗. 在win32编程中你会经常遇到DC这个词.
它是 Device Context 的缩写, 官方译为"设备描述表". 如果你研究过vc, 你应该对它不陌生. 不过如果你不明白它是什么
也不要紧. 你可以把它看作一个句柄. 就是某个设备或某块内存的名称.),然后把位图选进内存DC. 再用 GetObject 函数获得
位图的尺寸, 然后用 StretchBlt 把位图显示在窗口上. StretchBlt的作用和 BitBlt 一样,但它可以拉伸或压缩位图到我们
希望的大小. 在这里我们希望位图能适合窗口的大小,所以我们 StretchBlt 代替 BitBlt. 之后我们删除内存DC.
<p><b> .elseif uMsg==WM_LBUTTONDOWN </b>
<br>
<b>
invoke DestroyWindow,hWnd </b>
<p>如果你的程序的使用者每次都要看到启动画面消失才能用, 他们一定会厌烦. 我们可以为用户提供多一种选择.
当他单击启动画面, 它就会消失. 这就是为什么我们要在DLL里处理 WM_LBUTTONDOWN 消息.
收到这个消息后立即就用 DestroyWindow 关掉窗口.
<p> .elseif uMsg==WM_TIMER
<br>
<b>
invoke SendMessage,hWnd,WM_LBUTTONDOWN,NULL,NULL </b> <br>
<b>
invoke KillTimer,hWnd,TimerID </b>
<p>如果用户选择等待, 那么启动画面会在定时器到了指定的时间后消失. (在本例中, 是 2 秒). 我们可以通过处理
WM_TIMER 消息达到这一目的. 在收到这一消息后,我们可以对窗口传送 WM_LBUTTONDOWN 消息来关掉窗口. 这是为了避免
代码重复. 现在, 我们不再需要这个定时器了,所以我们用 KillTimer 删除它. <br>
窗口关闭后,DLL 把控制权还给主程序.
<hr size="1">
<div align="center"> 这篇文章来自于 Iczelion 的 asm 网页,本章由Pheadnius为大家翻译. Welcom to <a href="http://asm.yeah.net">http://asm.yeah.net</a></div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -