/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: Splash.cpp Abstract: Implementation of the splash screen class. Notes: ANSI & Unicode via TCHAR - runs on Win9x/NT/2K/XP etc. History: 01/30/01 rparsons Created 01/10/02 rparsons Revised 01/27/02 rparsons Converted to TCHAR --*/ #include "splash.h" /*++ Routine Description: Constructor - init member variables. Arguments: None. Return Value: None. --*/ CSplash::CSplash() { m_dwDuration = 0; m_dwSplashId = 0; } /*++ Routine Description: Does the work of creating the splash screen. Arguments: hInstance - Application instance handle. dwLoColorBitmapId - Low color bitmap identifier. dwHiColorBitmapId - Hight color bitmap identifier (OPTIONAL). dwDuration - Amount of time to display the splash screen (milliseconds). Return Value: None. --*/ void CSplash::Create( IN HINSTANCE hInstance, IN DWORD dwLoColorBitmapId, IN DWORD dwHiColorBitmapId OPTIONAL, IN DWORD dwDuration ) { HDC hDC; int nBitsInAPixel = 0; m_hInstance = hInstance; // // Get a handle to the display driver context and determine // the number of bits in a pixel. // hDC = GetDC(0); nBitsInAPixel = GetDeviceCaps(hDC, BITSPIXEL); ReleaseDC(NULL, hDC); // // If there are more than 8 bits in a pixel, and the high color // bitmap is available, use it. Otherwise, use the low color one. // if (nBitsInAPixel > 8 && dwHiColorBitmapId) { m_dwSplashId = dwHiColorBitmapId; } else { m_dwSplashId = dwLoColorBitmapId; } m_dwDuration = dwDuration * 1000; CSplash::InitSplashScreen(hInstance); CSplash::CreateSplashWindow(); } /*++ Routine Description: Sets up the window class struct for splash screen. Arguments: hInstance - Application instance handle. Return Value: TRUE on success, FALSE otherwise. --*/ BOOL CSplash::InitSplashScreen( IN HINSTANCE hInstance ) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = SplashWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = _T("SPLASHWIN"); return RegisterClass(&wc); } /*++ Routine Description: Creates the splash screen for the setup app. Arguments: None. Return Value: TRUE on success, FALSE otherwise. --*/ BOOL CSplash::CreateSplashWindow() { HBITMAP hBitmap; BITMAP bm; RECT rect; HWND hWnd; // // Load the bitmap and fill out a BITMAP structure for it. // hBitmap = LoadBitmap(m_hInstance, MAKEINTRESOURCE(m_dwSplashId)); GetObject(hBitmap, sizeof(bm), &bm); DeleteObject(hBitmap); GetWindowRect(GetDesktopWindow(), &rect); // // Create the splash screen window. // Specifying WS_EX_TOOLWINDOW keeps us out of the // taskbar. // hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, _T("SPLASHWIN"), NULL, WS_POPUP | WS_BORDER, (rect.right / 2) - (bm.bmWidth / 2), (rect.bottom / 2) - (bm.bmHeight / 2), bm.bmWidth, bm.bmHeight, NULL, NULL, m_hInstance, (LPVOID)this); if (hWnd) { ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); } return (hWnd ? TRUE : FALSE); } /*++ Routine Description: Runs the message loop for the splash screen. Arguments: hWnd - Window handle. uMsg - Windows message. wParam - Additional message info. lParam - Additional message info. Return Value: TRUE if the message was processed, FALSE otherwise. --*/ LRESULT CALLBACK CSplash::SplashWndProc( IN HWND hWnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { PAINTSTRUCT ps; HDC hdc; CSplash *pThis = (CSplash*)GetWindowLong(hWnd, GWL_USERDATA); switch (uMsg) { case WM_CREATE: { LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam; pThis = (CSplash*)(lpcs->lpCreateParams); SetWindowLong(hWnd, GWL_USERDATA, (LONG)pThis); // // Enable the timer - this sets the amount // of time the screen will be displayed. // SetTimer(hWnd, 0, pThis->m_dwDuration, NULL); break; } // // Handle the palette messages in case another app takes // over the palette // case WM_PALETTECHANGED: if ((HWND) wParam == hWnd) { return 0; } case WM_QUERYNEWPALETTE: InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); return TRUE; case WM_DESTROY: PostQuitMessage(0); break; case WM_TIMER: DestroyWindow(hWnd); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); pThis->DisplayBitmap(hWnd, pThis->m_dwSplashId); EndPaint(hWnd, &ps); break; // // Override this message so Windows doesn't try // to calculate size for the caption bar and stuff. // case WM_NCCALCSIZE: return 0; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return FALSE; } /*++ Routine Description: Builds a palette with a spectrum of colors. Arguments: None. Return Value: Handle to a spectrum palette on success or NULL on failure. --*/ HPALETTE CSplash::CreateSpectrumPalette() { HPALETTE hPal; LPLOGPALETTE lplgPal = NULL; BYTE red, green, blue; int nCount = 0; lplgPal = (LPLOGPALETTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * MAXPALETTE); if (!lplgPal) { return NULL; } // // Initialize members of the structure // and build the spectrum of colors. // lplgPal->palVersion = PALVERSION; lplgPal->palNumEntries = MAXPALETTE; red = green = blue = 0; for (nCount = 0; nCount < MAXPALETTE; nCount++) { lplgPal->palPalEntry[nCount].peRed = red; lplgPal->palPalEntry[nCount].peGreen = green; lplgPal->palPalEntry[nCount].peBlue = blue; lplgPal->palPalEntry[nCount].peFlags = 0; if (!(red += 32)) { if (!(green += 32)) { blue += 64; } } } hPal = CreatePalette(lplgPal); HeapFree(GetProcessHeap(), 0, lplgPal); return hPal; } /*++ Routine Description: Builds a palette from an RGBQUAD structure. Arguments: rgbqPalette - Array of RGBQUAD structs. cElements - Number of elements in the array. Return Value: Handle to a palette on success or NULL on failure. --*/ HPALETTE CSplash::CreatePaletteFromRGBQUAD( IN LPRGBQUAD rgbqPalette, IN WORD cElements ) { HPALETTE hPal; LPLOGPALETTE lplgPal = NULL; int nCount = 0; lplgPal = (LPLOGPALETTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * cElements); if (!lplgPal) { return NULL; } // // Initialize structure members and fill in palette colors. // lplgPal->palVersion = PALVERSION; lplgPal->palNumEntries = cElements; for (nCount = 0; nCount < cElements; nCount++) { lplgPal->palPalEntry[nCount].peRed = rgbqPalette[nCount].rgbRed; lplgPal->palPalEntry[nCount].peGreen = rgbqPalette[nCount].rgbGreen; lplgPal->palPalEntry[nCount].peBlue = rgbqPalette[nCount].rgbBlue; lplgPal->palPalEntry[nCount].peFlags = 0; } hPal = CreatePalette(lplgPal); HeapFree(GetProcessHeap(), 0, lplgPal); return hPal; } /*++ Routine Description: Displays the bitmap in the specified window. Arguments: hWnd - Handle to the destination window. dwResId - Resource identifier for the bitmap. Return Value: None. --*/ void CSplash::DisplayBitmap( IN HWND hWnd, IN DWORD dwResId ) { HBITMAP hBitmap; HPALETTE hPalette; HDC hdcMemory = NULL, hdcWindow = NULL; BITMAP bm; RECT rect; RGBQUAD rgbq[256]; CSplash *pThis = (CSplash*)GetWindowLong(hWnd, GWL_USERDATA); GetClientRect(hWnd, &rect); // // Load the resource as a DIB section. // hBitmap = (HBITMAP)LoadImage(pThis->m_hInstance, MAKEINTRESOURCE(dwResId), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); GetObject(hBitmap, sizeof(BITMAP), (LPWSTR)&bm); hdcWindow = GetDC(hWnd); // // Create a DC to hold our surface and selct our surface into it. // hdcMemory = CreateCompatibleDC(hdcWindow); SelectObject(hdcMemory, hBitmap); // // Retrieve the color table (if there is one) and create a palette // that reflects it. // if (GetDIBColorTable(hdcMemory, 0, 256, rgbq)) { hPalette = CreatePaletteFromRGBQUAD(rgbq, 256); } else { hPalette = CreateSpectrumPalette(); } // // Select and realize the palette into our window DC. // SelectPalette(hdcWindow, hPalette, FALSE); RealizePalette(hdcWindow); // // Display the bitmap. // SetStretchBltMode(hdcWindow, COLORONCOLOR); StretchBlt(hdcWindow, 0, 0, rect.right, rect.bottom, hdcMemory, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); // // Clean up our objects. // DeleteDC(hdcMemory); DeleteObject(hBitmap); ReleaseDC(hWnd, hdcWindow); DeleteObject(hPalette); }