ICZelion Tut26

zhaozj2021-02-11  187

Tutorial 26: Splash Screen

Now That We know how to use a bitmap, we can progress to a more create use of it. Splash screen. Download

The example.

TheoryA splash screen is a window that has no title bar, no system menu box, no border that displays a bitmap for a while and then disappears automatically. It's usually used during program startup, to display the program's logo or to distract the user's attention while .

The first step is to include the bitmap in the resource file. However, if you think of it, it's a waste of precious memory to load a bitmap that will be used only once and keep it in memory till the program is closed. A better solution is to create a * resource * DLL which contains the bitmap and has the sole purpose of displaying the splash screen. This way, you can load the DLL when you want to display the splash screen and unload it when it's not necessary anymore. So WE WILL HAVE TWO MODULES: The Main Program and The Splash DLL. We Will Put The Bitmap INTO The DLL'S RESOURCE.

The General Scheme IS FOLLOWS:

Put the bitmap into the DLL as a bitmap resource The main program calls LoadLibrary to load the dll into memory The DLL entrypoint function of the DLL is called. It will create a timer and set the length of time that the splash screen will be displayed. Next it will register and create a window without caption and border and display the bitmap in the client area. When the specified length of time elapsed, the splash screen is removed from the screen and the control is returned to the main program The main program calls FreeLibrary to unload the DLL from memory and then goes on with whatever task it is supposed to do We will examine the mechanisms in detail.Load / unload DLLYou can dynamically load a DLL with LoadLibrary function which has the following syntax.:

LoadLibrary Proto LPDLLNAME: DWORD

IT Takes Only One Parameter: The Address of the Name of The DLL You Want To Load Into Memory. IT Returns The Module Handle of The DLL Else It Returns Null.

To Unload A DLL, Call FreeElibrary:

Freeelibrary Proto Hlib: DWORD

IT Takes One Parameter: The Module Handle of The DLL You Want To Unload. Normally, You Got That Handle from LoadLibrary

How To Use a Timerfirst, You Must Create a Timer First with SetTimer:

Settimer Proto Hwnd: DWORD, TIMERID: DWORD, UELAPSE: DWORD, LPTIMERFUNC: DWORD

hWnd is the handle of a window that will receive the timer notification message. This parameter can be NULL to specify that there is no window that's associated with the timer. TimerID is a user-defined value that is used as the ID of the timer. uElapse is the time-out value in milliseconds. lpTimerFunc is the address of a function that will process the timer notification messages. If you pass NULL, the timer messages will be sent to the window specified by hWnd parameter.SetTimer returns the ID of the Timer if success Returns Null. SO it's best not to use the timer id of 0.

You can create a Timer in Two Ways:

If you have a window and you want the timer notification messages to go to that window, you must pass all four parameters to SetTimer (the lpTimerFunc must be NULL) If you do not have a window or you do not want to process the timer messages in the window procedure, you must pass NULL to the function in place of a window handle. you must also specify the address of the timer function that will process the timer messages. We will use the first approach in this example.

.

When you don't need the Timer Anymore, Destroy It with killtimer:

Killtimer Proto Hwnd: DWORD, TIMERID: DWORD

Example:; ----------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------

; The main program

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

.386

.Model flat, stdcall

Option CaseMAP: NONE

INCLUDE /MASM32/INCLUDE/Windows.inc

Include /masm32/include/User32.incinclude /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 invok E 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; ---------------------------------------------------------------- -------------------------------------------------- ----------------------------------------- .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 includeelib /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 mov DlgWidth, eax push eax mov eax, DesktopRect.bottom sub eax, DlgHeight shr eax, 1 Push Eax Mov Eax, DesktopRect.right Sub Eax, DLGWIDTH SHR Eax, 1 Push Eax Push Hwnd Call MoveWindow invoke LoadBitmap, hInstance, addr BitmapName mov hBitMap, eax invoke SetTimer, hWnd, 1,2000, NULL mov TimerID, eax .elseif uMsg == WM_TIMER invoke SendMessage, hWnd, WM_LBUTTONDOWN, NULL, NULL invoke KillTimer, hWnd, TimerID .elseif uMsg ==

WM_PAINT invoke BeginPaint, hWnd, addr ps mov hdc, eax invoke CreateCompatibleDC, hdc mov hMemoryDC, eax invoke SelectObject, eax, hBitMap mov hOldBmp, eax invoke GetObject, hBitMap, sizeof BITMAP, addr bitmap invoke StretchBlt, hdc, 0,0,250,250, / hMemoryDC, 0,0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY invoke SelectObject, hMemoryDC, hOldBmp invoke DeleteDC, hMemoryDC invoke EndPaint, hWnd, addr ps .elseif uMsg == WM_LBUTTONDOWN invoke DestroyWindow, hWnd .else invoke DefWindowProc, hWnd, uMsg , WPARAM, LPARAM RET .Endif Xor Eax, EAX RET WNDPROC Endpend DLLENTRY

Analysis: We Will Examine The Code in The Main Program First.

Invoke LoadLibrary, Addr Libname

.IF EAX! = NULL

Invoke Freelibrary, EAX

.endif

We call LoadLibrary to load the dll name "splash.dll". And after this, unloaded it from memory with freeelibrary. LoadingLibrary will not return until the dll is finished with its initialization.

That's all the main program does. The Interesting Part IS in The DLL.

.IF real_attach; when the dll is loading push hinst pop hinstance call showbitmap

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:. INVOKE CreateWindowEx, NULL, ADDR ClassName, NULL, / WS_POPUP, CW_USEDEFAULT, / CW_USEDEFAULT, 250,250, NULL, NULL, / Hinstance, null

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. Now when the window is created, in WM_CREATE message handler we move the window to the center Of the screen with the folload code.

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 mov DlgWidth, eax push eax mov eax, DesktopRect.bottom sub eax, DlgHeight shr eax, 1 push eax mov eax, DesktopRect.right sub eax, DlgWidth shr eax, 1 push eax push hWnd call MoveWindow

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.invoke LoadBitmap, hInstance, addr BitmapName mov hBitMap, eax invoke SetTimer, hWnd, 1,2000, NULL mov Timerid, EAX

NEXT IT LOADS The Bitmap From The Resource with LoadBitmap and create 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.

.elseif uMsg == WM_PAINT invoke BeginPaint, hWnd, addr ps mov hdc, eax invoke CreateCompatibleDC, hdc mov hMemoryDC, eax invoke SelectObject, eax, hBitMap mov hOldBmp, eax invoke GetObject, hBitMap, sizeof BITMAP, addr bitmap invoke StretchBlt, hdc, 0,0,250,250, / hmemorydc, 0,0, bitmap.bmwidth, Bitmap.bmheight, Srcopy Invoke Selectobject, HMemorydc, Holdbmp Invoke deletedc, HMemorydc Invoke Endpaint, HWnd, Addr PS

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 bitmppy. we...

.ELSEIF UMSG == WM_LButtondown Invoke DestroyWindow, Hwnd

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..lseif umsg == wm_timer invoke sendmessage, hwnd, wm_lbuttondown, null, null invoke killtimer, hwnd, timerid

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. we don't have destroy it for the timer sowe destroy it with killtimer .hen the window is close, the dress............

转载请注明原文地址:https://www.9cbs.com/read-4664.html

New Post(0)