winsplash.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:10k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // winsplash.cpp
  2. //
  3. // Copyright (C) 2005, Chris Laurel <claurel@shatters.net>
  4. //
  5. // Win32 splash window
  6. //
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the GNU General Public License
  9. // as published by the Free Software Foundation; either version 2
  10. // of the License, or (at your option) any later version.
  11. #include "winsplash.h"
  12. #include <string>
  13. #include <winuser.h>
  14. #include <commctrl.h>
  15. #include "res/resource.h"
  16. #include <iostream>
  17. using namespace std;
  18. // Required for transparent Windows, but not present in VC6 headers. Only present
  19. // on Win2k or later.
  20. typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)
  21.         (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags);
  22. typedef BOOL (WINAPI *lpfnUpdateLayeredWindow)
  23.         (HWND hwnd, HDC hdcDst, POINT* pptDst, SIZE* psize,
  24.          HDC hdcSrc, POINT* pptSrc, COLORREF crKey, BLENDFUNCTION* pblend,
  25.          DWORD dwFlags);
  26. lpfnSetLayeredWindowAttributes winSetLayeredWindowAttributes = NULL;
  27. lpfnUpdateLayeredWindow        winUpdateLayeredWindow = NULL;
  28. #define WS_EX_LAYERED 0x00080000 
  29. #define LWA_COLORKEY  1
  30. #define LWA_ALPHA     2
  31. #define ULW_COLORKEY  1
  32. #define ULW_ALPHA     2
  33. #define ULW_OPAQUE    4
  34. static LRESULT CALLBACK SplashWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  35. {
  36.     static SplashWindow *splash = NULL;
  37.     
  38.     if (uMsg == WM_CREATE)
  39.     {
  40.         splash = reinterpret_cast<SplashWindow*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
  41.     }
  42.     
  43.     if (splash)
  44.         return splash->windowProc(hwnd, uMsg, wParam, lParam);
  45.     else
  46.         return DefWindowProc(hwnd, uMsg, wParam, lParam);
  47. }
  48. SplashWindow::SplashWindow(const string& _imageFileName) :
  49.     hwnd(NULL),
  50.     className(NULL),
  51.     imageFileName(_imageFileName),
  52.     image(NULL),
  53.     hBitmap(0),
  54.     hCompositionBitmap(0),
  55.     useLayeredWindow(false),
  56.     winWidth(640),
  57.     winHeight(480)
  58. {
  59.     init();
  60. }
  61. SplashWindow::~SplashWindow()
  62. {
  63.     if (hBitmap)
  64.         ::DeleteObject(hBitmap);
  65.     if (hCompositionBitmap)
  66.         ::DeleteObject(hCompositionBitmap);
  67. }
  68. LRESULT CALLBACK
  69. SplashWindow::windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  70. {
  71.     switch (uMsg)
  72.     {
  73.         case WM_PAINT:
  74.             if (!useLayeredWindow)
  75.             {
  76.                 PAINTSTRUCT ps;
  77.                 HDC hDC = BeginPaint(hwnd, &ps);
  78.                 paint(hDC);
  79.                 EndPaint(hwnd, &ps);
  80.             }
  81.             return TRUE;            
  82.     }
  83.     return DefWindowProc (hwnd, uMsg, wParam, lParam) ;
  84. }
  85. void
  86. SplashWindow::paint(HDC hDC)
  87. {
  88.     RECT rect;
  89.     ::GetClientRect(hwnd, &rect);
  90.     if (hBitmap)
  91.     {
  92.         // Display the splash image
  93.         HDC hMemDC      = ::CreateCompatibleDC(hDC);   
  94.         HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hMemDC, hBitmap);
  95.     
  96.         BitBlt(hDC, 0, 0, winWidth, winHeight, hMemDC, 0, 0, SRCCOPY);
  97.         
  98.         ::SelectObject(hMemDC, hOldBitmap);
  99.         ::DeleteDC(hMemDC);
  100.         
  101.         SetTextColor(hDC, RGB(255, 255, 255));
  102.         SetBkMode(hDC, TRANSPARENT);        
  103.     }
  104.     else
  105.     {
  106.         // If the splash image couldn't be loaded, just paint a black background
  107.         HBRUSH hbrush = CreateSolidBrush(RGB(0, 0, 0));
  108.         FillRect(hDC, &rect, hbrush);
  109.         DeleteObject(hbrush);        
  110.     }
  111.     
  112.     // Show the message text
  113.     RECT r;
  114.     r.left   = rect.right - 250;
  115.     r.top    = rect.bottom - 70;
  116.     r.right  = rect.right;
  117.     r.bottom = r.top + 30;
  118.         
  119.     HFONT hFont = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
  120.     SelectObject(hDC, hFont);
  121.     
  122.     string text = string("Version " VERSION_STRING "n") + message;
  123.     DrawText(hDC, text.c_str(), text.length(), &r, DT_LEFT | DT_VCENTER);
  124. }
  125. void
  126. SplashWindow::init()
  127. {
  128.     hwnd = NULL;
  129.     className = TEXT("CELSPLASH");
  130.     //  Get the function pointer for SetLayeredWindowAttributes
  131.     HMODULE user32 = GetModuleHandle(TEXT("USER32.DLL"));
  132.     winSetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes) GetProcAddress(user32, "SetLayeredWindowAttributes");
  133.     winUpdateLayeredWindow = (lpfnUpdateLayeredWindow) GetProcAddress(user32, "UpdateLayeredWindow");
  134.     
  135.     if (winSetLayeredWindowAttributes != NULL && winUpdateLayeredWindow != NULL)
  136.         useLayeredWindow = true;
  137.         
  138.     image = LoadImageFromFile(imageFileName);    
  139. }
  140. void
  141. SplashWindow::updateWindow()
  142. {
  143.     // If we're using layered windows, draw into the compositing bitmap and use it to
  144.     // as the source for UpdateLayeredWindow. Otherwise, we use the traditional approach
  145.     // and send a paint message to the window.
  146.     if (useLayeredWindow)
  147.     {
  148.         HDC hwndDC = GetDC(hwnd);
  149.         HDC hDC = CreateCompatibleDC(hwndDC);
  150.         
  151.         HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hDC, hCompositionBitmap);
  152.         paint(hDC);
  153.         
  154.         SIZE size;
  155.         POINT origin = { 0, 0 };
  156.         size.cx = winWidth;
  157.         size.cy = winHeight;
  158.         BLENDFUNCTION blend;
  159.         blend.BlendOp = AC_SRC_OVER;
  160.         blend.BlendFlags = 0;
  161.         blend.AlphaFormat = AC_SRC_ALPHA;
  162.         blend.SourceConstantAlpha = 0xff;
  163.         winUpdateLayeredWindow(hwnd, hwndDC, NULL, &size, hDC, &origin, 0, &blend, ULW_ALPHA);
  164.         ::SelectObject(hDC, hOldBitmap);
  165.         ::DeleteDC(hDC);
  166.     }
  167.     
  168.     ::UpdateWindow(hwnd);
  169. }
  170. HWND
  171. SplashWindow::createWindow()
  172. {
  173.     WNDCLASSEX wndclass;
  174.     wndclass.cbSize         = sizeof (wndclass);
  175.     wndclass.style          = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW;
  176.     wndclass.lpfnWndProc    = SplashWndProc;
  177.     wndclass.cbClsExtra     = 0;
  178.     wndclass.cbWndExtra     = DLGWINDOWEXTRA;
  179.     wndclass.hInstance      = ::GetModuleHandle(NULL);
  180.     wndclass.hIcon          = NULL;
  181.     wndclass.hCursor        = ::LoadCursor( NULL, IDC_WAIT );
  182.     wndclass.hbrBackground  = (HBRUSH)::GetStockObject(LTGRAY_BRUSH);
  183.     wndclass.lpszMenuName   = NULL;
  184.     wndclass.lpszClassName  = className;
  185.     wndclass.hIconSm        = NULL;
  186.     if (!RegisterClassEx(&wndclass))
  187.         return NULL;
  188.     if (image != NULL)
  189.     {
  190.         winWidth = image->getWidth();
  191.         winHeight = image->getHeight();
  192.     }
  193.     // Create the application window centered in the middle of the screen
  194.     DWORD nScrWidth  = ::GetSystemMetrics(SM_CXFULLSCREEN);
  195.     DWORD nScrHeight = ::GetSystemMetrics(SM_CYFULLSCREEN);
  196.     int x = (nScrWidth  - winWidth) / 2;
  197.     int y = (nScrHeight - winHeight) / 2;
  198.     hwnd = ::CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, className, 
  199.                             TEXT("Banner"), WS_POPUP, x, y, 
  200.                             winWidth, winHeight, NULL, NULL, NULL, this);
  201.     if (hwnd)
  202.     {
  203.         createBitmap();
  204.         
  205.         // If this version of Windows supports layered windows, set the window
  206.         // style to layered.
  207.         if (useLayeredWindow)
  208.         {
  209.             SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
  210.         }
  211.         
  212.         ShowWindow(hwnd, SW_SHOW);
  213.         updateWindow();
  214.     }
  215.  
  216.     delete image;
  217.     image = NULL;
  218.  
  219.     return hwnd;
  220. }
  221. bool
  222. SplashWindow::createBitmap()
  223. {
  224.     if (image != NULL)
  225.     {
  226.         BITMAPINFO bmi;
  227.         ZeroMemory(&bmi, sizeof(bmi));
  228.         bmi.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
  229.         bmi.bmiHeader.biWidth    = image->getWidth();
  230.         bmi.bmiHeader.biHeight   = image->getHeight();
  231.         bmi.bmiHeader.biPlanes   = 1;
  232.         bmi.bmiHeader.biBitCount = 32;
  233.         bmi.bmiHeader.biCompression = BI_RGB;
  234.         bmi.bmiHeader.biSizeImage = image->getWidth() * image->getHeight() * 4;
  235.         HDC hwndDC = GetDC(hwnd);
  236.         HDC hDC = CreateCompatibleDC(hwndDC);
  237.         
  238.         void* bmPixels = NULL;
  239.         
  240.         // create our DIB section and select the bitmap into the dc
  241.         hBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &bmPixels, NULL, 0x0);
  242.         
  243.         // Windows bitmaps are upside-down and the order of the color channels is different
  244.         // than for a PNG. When copying pixels to the bitmap, we remap the color channels and
  245.         // flip the image vertically.
  246.         if (bmPixels != NULL)
  247.         {
  248.             unsigned char* src = image->getPixels();
  249.             unsigned char* dst = reinterpret_cast<unsigned char*>(bmPixels);
  250.             
  251.             for (unsigned int i = 0; i < (unsigned int) image->getHeight(); i++)
  252.             {
  253.                 for (unsigned int j = 0; j < (unsigned int) image->getWidth(); j++)
  254.                 {
  255.                     unsigned char* srcPix = &src[4 * (image->getWidth() * (image->getHeight() - i - 1) + j)];
  256.                     unsigned char* dstPix = &dst[4 * (image->getWidth() * i + j)];
  257.                     
  258.                     // Windows requires that we premultiply by alpha
  259.                     unsigned int alpha = srcPix[3];
  260.                     dstPix[0] = (unsigned char) ((srcPix[2] * alpha) / 255);
  261.                     dstPix[1] = (unsigned char) ((srcPix[1] * alpha) / 255);
  262.                     dstPix[2] = (unsigned char) ((srcPix[0] * alpha) / 255);
  263.                     dstPix[3] = srcPix[3];
  264.                 }
  265.             }
  266.         }
  267.         
  268.         DeleteDC(hDC);
  269.         
  270.         // Create the composition bitmap (always created, though it's only used when we've got
  271.         // layered window support.)
  272.         if (hBitmap)
  273.         {
  274.             hCompositionBitmap = CreateCompatibleBitmap(hwndDC, image->getWidth(), image->getHeight());
  275.         }
  276.     }
  277.     
  278.     return hBitmap != 0 && hCompositionBitmap != 0;
  279. }
  280. int SplashWindow::messageLoop()
  281. {
  282.     if (!hwnd)
  283.         showSplash();
  284.     MSG msg;
  285.     while (GetMessage(&msg, NULL, 0, 0))
  286.     {
  287.         TranslateMessage(&msg);
  288.         DispatchMessage(&msg);
  289.     }
  290.     return msg.wParam ;
  291. }
  292. // Redraw the window with a new text message
  293. void SplashWindow::setMessage(const string& msg)
  294. {
  295.     message = msg;
  296.     InvalidateRect(hwnd, NULL, FALSE);
  297.     updateWindow();
  298. }
  299. void SplashWindow::showSplash()
  300. {
  301.     close();
  302.     createWindow();
  303. }
  304. int SplashWindow::close()
  305. {
  306.     
  307.     if (hwnd)
  308.     {
  309.         DestroyWindow(hwnd);
  310.         hwnd = 0;
  311.         UnregisterClass(className, ::GetModuleHandle(NULL));
  312.         return 1;
  313.     }
  314.     
  315.     return 0;
  316. }