📄 lion-tutorial26.htm
字号:
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> Analysis:</h3>
We will examine the code in the main program first.
<blockquote><b> invoke LoadLibrary,addr Libname </b> <br>
<b> .if eax!=NULL </b> <br>
<b> invoke FreeLibrary,eax </b> <br>
<b> .endif </b></blockquote>
We call LoadLibrary to load the DLL named "splash.dll". And after that, unload
it from memory with FreeLibrary. LoadLibrary will not return until the DLL is
finished with its initialization. <br>
That's all the main program does. The interesting part is in the 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>When the DLL is loaded, Windows calls its entrypoint function with DLL_PROCESS_ATTACH
flag. We take this opportunity to display the splash screen. First we store
the instance handle of the DLL for future use. Then call a function named ShowBitMap
to do the real job. ShowBitMap registers a window class, creates a window and
enters the message loop as usual. The interesting part is in the CreateWindowEx
call:
<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>Note that the window style is only WS_POPUP which will make the window borderless
and without caption. We also limit the width and height of the window to 250x250
pixels. <br>
Now when the window is created, in WM_CREATE message handler we move the window
to the center of the screen with the following code.
<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>It retrieves the dimensions of the desktop and the window then calculates the
appropriate coordinate of the left upper corner of the window to make it center.
<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>Next it loads the bitmap from the resource with LoadBitmap and creates a timer
with the timer ID of 1 and the time interval 2 seconds. The timer will send
WM_TIMER messages to the window every 2 seconds.
<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>When the window receives WM_PAINT message, it creates a memory DC, select the
bitmap into the memory DC, obtain the size of the bitmap with GetObject and
then put the bitmap on the window by calling StretchBlt which performs like
BitBlt but it can stretch or compress the bitmap to the desired dimension. In
this case, we want the bitmap to fit into the window so we use StretchBlt instead
of BitBlt. We delete the memory DC after that.
<p><b> .elseif uMsg==WM_LBUTTONDOWN </b>
<br>
<b>
invoke DestroyWindow,hWnd </b>
<p>It would be frustrating to the user if he has to wait until the splash screen
to disappear. We can provide the user with a choice. When he clicks on the splash
screen, it will disappear. That's why we need to process WM_LBUTTONDOWN message
in the DLL. Upon receiving this message, the window is destroyed by DestroyWindow
call.
<p> .elseif uMsg==WM_TIMER
<br>
<b>
invoke SendMessage,hWnd,WM_LBUTTONDOWN,NULL,NULL </b> <br>
<b>
invoke KillTimer,hWnd,TimerID </b>
<p>If the user chooses to wait, the splash screen will disappear when the specified
time has elapsed (in our example, it's 2 seconds). We can do this by processing
WM_TIMER message. Upon receiving this message, we closes the window by sending
WM_LBUTTONDOWN message to the window. This is to avoid code duplication. We
don't have further use for the timer so we destroy it with KillTimer. <br>
When the window is closed, the DLL will return control to the main program.
<hr size="1">
<div align="center"> This article come from Iczelion's asm page, 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 + -