// splash.cpp - main application implementation file//// Includes//#define WIN32_LEAN_AND_MEAN#include <windows.h>#include "resource.h"//// Global Constants - used by global functions in this file//const char SZ_SPLASHWNDCLASS[] = "SplashWndClass";//// Global Variables - used by global functions in this file//HINSTANCE g_hInstance;//// Forward Declarations of functions called from WinMain below//HWND ShowSplash();void DestroySplash(HWND hWndSplash);//// Entry Point - function that gets called when program starts//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){ // Do pre-splash initialization here... // Save instance g_hInstance = hInstance; // Show splash HWND hWndSplash = ShowSplash(); // Do heavy initialization here while splash is shown... // Sleep() function is async, so it effectively "hangs" your code to simulate heavy processing Sleep(5000); // Destroy splash DestroySplash(hWndSplash); // Start message loop and show main window, etc.... return 0;}LRESULT CALLBACK SplashWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ static HBITMAP hbmSplash; // bitmap to display (loaded from resources) static HDC hdcSplash; // device context used to contain the bitmap in order to enable blitting static HBITMAP hbmOldSplash; // save device context's default bitmap to restore it later static SIZE bitmapSize; // saved size of splash bitmap switch(uMsg) { case WM_CREATE: { // This is the first message to get sent to a window. // Modify window style to remove window frame (because Windows adds them no matter what) SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & WS_BORDER); // Load the bitmap to be shown // Use IDB_SPLASH resource ID (you must first add a bitmap resource with that ID to your resources) hbmSplash = LoadBitmap(g_hInstance, (LPCTSTR)IDB_SPLASH); if(!hbmSplash) { // Failed to load splash bitmap, probably because it's not in resources. Cancel. return 1; } // Create a device context to contain the bitmap, compatible with this window's device context HDC hDC = GetDC(hWnd); hdcSplash = CreateCompatibleDC(hDC); ReleaseDC(hWnd, hDC); // Select loaded bitmap into that device context, and save its default bitmap hbmOldSplash = (HBITMAP)SelectObject(hdcSplash, hbmSplash); // Move and resize the splash according to size of bitmap being displayed // Find out the size of the bitmap we loaded and also save it for later BITMAP bi; GetObject(hbmSplash, sizeof(BITMAPINFO), (LPVOID)&bi); bitmapSize.cx = bi.bmWidth; bitmapSize.cy = bi.bmHeight; // Find out the size of screen space not obscured by taskbar RECT rcWorkArea; SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rcWorkArea, 0); // That's enough information to re-position and resize splash window... // Take into account the borders and title bar that haven't been removed yet MoveWindow( hWnd, (rcWorkArea.right - rcWorkArea.left - bi.bmWidth) / 2, (rcWorkArea.bottom - rcWorkArea.top - bi.bmHeight) / 2, bi.bmWidth, bi.bmHeight, TRUE); return 0; } break; case WM_DESTROY: { // Clean up objects we created in WM_CREATE here SelectObject(hdcSplash, hbmOldSplash); DeleteDC(hdcSplash); // hbmSplash needs no cleanup, it will be released automatically by Windows } break; case WM_PAINT: { // Simply paint the splash image here by copying a rectangle of pixel values from // splash device context to splash window device context PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd, &ps); RECT rcClient; GetClientRect(hWnd, &rcClient); // Get size of our visible area BitBlt(hDC, 0, 0, rcClient.right, rcClient.bottom, hdcSplash, 0, 0, SRCCOPY); EndPaint(hWnd, &ps); return 0; } break; } // If we get any other kind of message, pass it to DefWindowProc for default processing return DefWindowProc(hWnd, uMsg, wParam, lParam);}HWND ShowSplash(){ // Register splash window class... WNDCLASSEX wcx = {0}; wcx.cbSize = sizeof(wcx); wcx.hInstance = g_hInstance; wcx.lpszClassName = SZ_SPLASHWNDCLASS; wcx.lpfnWndProc = SplashWndProc; if(!RegisterClassEx(&wcx)) { // Failed to register splash window class, return 0 to indicate failure return NULL; } // Create splash window - it will position and resize itself so we don't care about position/size here // Pass uBitmapResourceID as the creation param, so splash wndproc's WM_CREATE handler will know what bitmap to load HWND hWnd = CreateWindowEx(0, SZ_SPLASHWNDCLASS, NULL, 0, 0, 0, 100, 100, NULL, NULL, g_hInstance, NULL); if(!hWnd) return NULL; // Show splash window and repaint it for the first time ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); return hWnd;}void DestroySplash(HWND hWndSplash){ // Destroy the splash window, if handle is valid if(IsWindow(hWndSplash)) DestroyWindow(hWndSplash);}