00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "winsplash.h"
00013 #include <string>
00014 #include <winuser.h>
00015 #include <commctrl.h>
00016 #include "res/resource.h"
00017 #include <iostream>
00018
00019 using namespace std;
00020
00021
00022
00023
00024 typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)
00025 (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags);
00026 typedef BOOL (WINAPI *lpfnUpdateLayeredWindow)
00027 (HWND hwnd, HDC hdcDst, POINT* pptDst, SIZE* psize,
00028 HDC hdcSrc, POINT* pptSrc, COLORREF crKey, BLENDFUNCTION* pblend,
00029 DWORD dwFlags);
00030
00031 lpfnSetLayeredWindowAttributes winSetLayeredWindowAttributes = NULL;
00032 lpfnUpdateLayeredWindow winUpdateLayeredWindow = NULL;
00033
00034 #define WS_EX_LAYERED 0x00080000
00035 #define LWA_COLORKEY 1
00036 #define LWA_ALPHA 2
00037
00038 #define ULW_COLORKEY 1
00039 #define ULW_ALPHA 2
00040 #define ULW_OPAQUE 4
00041
00042
00043 static LRESULT CALLBACK SplashWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00044 {
00045 static SplashWindow *splash = NULL;
00046
00047 if (uMsg == WM_CREATE)
00048 {
00049 splash = reinterpret_cast<SplashWindow*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
00050 }
00051
00052 if (splash)
00053 return splash->windowProc(hwnd, uMsg, wParam, lParam);
00054 else
00055 return DefWindowProc(hwnd, uMsg, wParam, lParam);
00056 }
00057
00058
00059 SplashWindow::SplashWindow(const string& _imageFileName) :
00060 hwnd(NULL),
00061 className(NULL),
00062 imageFileName(_imageFileName),
00063 image(NULL),
00064 hBitmap(0),
00065 hCompositionBitmap(0),
00066 useLayeredWindow(false),
00067 winWidth(640),
00068 winHeight(480)
00069 {
00070 init();
00071 }
00072
00073
00074 SplashWindow::~SplashWindow()
00075 {
00076 if (hBitmap)
00077 ::DeleteObject(hBitmap);
00078 if (hCompositionBitmap)
00079 ::DeleteObject(hCompositionBitmap);
00080 }
00081
00082
00083 LRESULT CALLBACK
00084 SplashWindow::windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00085 {
00086 switch (uMsg)
00087 {
00088 case WM_PAINT:
00089 if (!useLayeredWindow)
00090 {
00091 PAINTSTRUCT ps;
00092 HDC hDC = BeginPaint(hwnd, &ps);
00093 paint(hDC);
00094 EndPaint(hwnd, &ps);
00095 }
00096 return TRUE;
00097 }
00098
00099 return DefWindowProc (hwnd, uMsg, wParam, lParam) ;
00100 }
00101
00102
00103 void
00104 SplashWindow::paint(HDC hDC)
00105 {
00106 RECT rect;
00107 ::GetClientRect(hwnd, &rect);
00108
00109 if (hBitmap)
00110 {
00111
00112 HDC hMemDC = ::CreateCompatibleDC(hDC);
00113 HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hMemDC, hBitmap);
00114
00115 BitBlt(hDC, 0, 0, winWidth, winHeight, hMemDC, 0, 0, SRCCOPY);
00116
00117 ::SelectObject(hMemDC, hOldBitmap);
00118 ::DeleteDC(hMemDC);
00119
00120 SetTextColor(hDC, RGB(255, 255, 255));
00121 SetBkMode(hDC, TRANSPARENT);
00122 }
00123 else
00124 {
00125
00126 HBRUSH hbrush = CreateSolidBrush(RGB(0, 0, 0));
00127 FillRect(hDC, &rect, hbrush);
00128 DeleteObject(hbrush);
00129 }
00130
00131
00132 RECT r;
00133 r.left = rect.right - 250;
00134 r.top = rect.bottom - 70;
00135 r.right = rect.right;
00136 r.bottom = r.top + 30;
00137
00138 HFONT hFont = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
00139 SelectObject(hDC, hFont);
00140
00141 string text = string("Version " VERSION_STRING "\n") + message;
00142 DrawText(hDC, text.c_str(), text.length(), &r, DT_LEFT | DT_VCENTER);
00143 }
00144
00145
00146 void
00147 SplashWindow::init()
00148 {
00149 hwnd = NULL;
00150 className = TEXT("CELSPLASH");
00151
00152
00153 HMODULE user32 = GetModuleHandle(TEXT("USER32.DLL"));
00154
00155 winSetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes) GetProcAddress(user32, "SetLayeredWindowAttributes");
00156 winUpdateLayeredWindow = (lpfnUpdateLayeredWindow) GetProcAddress(user32, "UpdateLayeredWindow");
00157
00158 if (winSetLayeredWindowAttributes != NULL && winUpdateLayeredWindow != NULL)
00159 useLayeredWindow = true;
00160
00161 image = LoadImageFromFile(imageFileName);
00162 }
00163
00164
00165 void
00166 SplashWindow::updateWindow()
00167 {
00168
00169
00170
00171 if (useLayeredWindow)
00172 {
00173 HDC hwndDC = GetDC(hwnd);
00174 HDC hDC = CreateCompatibleDC(hwndDC);
00175
00176 HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hDC, hCompositionBitmap);
00177 paint(hDC);
00178
00179 SIZE size;
00180 POINT origin = { 0, 0 };
00181 size.cx = winWidth;
00182 size.cy = winHeight;
00183 BLENDFUNCTION blend;
00184 blend.BlendOp = AC_SRC_OVER;
00185 blend.BlendFlags = 0;
00186 blend.AlphaFormat = AC_SRC_ALPHA;
00187 blend.SourceConstantAlpha = 0xff;
00188 winUpdateLayeredWindow(hwnd, hwndDC, NULL, &size, hDC, &origin, 0, &blend, ULW_ALPHA);
00189
00190 ::SelectObject(hDC, hOldBitmap);
00191 ::DeleteDC(hDC);
00192 }
00193
00194 ::UpdateWindow(hwnd);
00195 }
00196
00197
00198 HWND
00199 SplashWindow::createWindow()
00200 {
00201 WNDCLASSEX wndclass;
00202 wndclass.cbSize = sizeof (wndclass);
00203 wndclass.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW;
00204 wndclass.lpfnWndProc = SplashWndProc;
00205 wndclass.cbClsExtra = 0;
00206 wndclass.cbWndExtra = DLGWINDOWEXTRA;
00207 wndclass.hInstance = ::GetModuleHandle(NULL);
00208 wndclass.hIcon = NULL;
00209 wndclass.hCursor = ::LoadCursor( NULL, IDC_WAIT );
00210 wndclass.hbrBackground = (HBRUSH)::GetStockObject(LTGRAY_BRUSH);
00211 wndclass.lpszMenuName = NULL;
00212 wndclass.lpszClassName = className;
00213 wndclass.hIconSm = NULL;
00214
00215 if (!RegisterClassEx(&wndclass))
00216 return NULL;
00217
00218 if (image != NULL)
00219 {
00220 winWidth = image->getWidth();
00221 winHeight = image->getHeight();
00222 }
00223
00224
00225 DWORD nScrWidth = ::GetSystemMetrics(SM_CXFULLSCREEN);
00226 DWORD nScrHeight = ::GetSystemMetrics(SM_CYFULLSCREEN);
00227
00228 int x = (nScrWidth - winWidth) / 2;
00229 int y = (nScrHeight - winHeight) / 2;
00230 hwnd = ::CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, className,
00231 TEXT("Banner"), WS_POPUP, x, y,
00232 winWidth, winHeight, NULL, NULL, NULL, this);
00233
00234 if (hwnd)
00235 {
00236 createBitmap();
00237
00238
00239
00240 if (useLayeredWindow)
00241 {
00242 SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
00243 }
00244
00245 ShowWindow(hwnd, SW_SHOW);
00246 updateWindow();
00247 }
00248
00249 delete image;
00250 image = NULL;
00251
00252 return hwnd;
00253 }
00254
00255
00256 bool
00257 SplashWindow::createBitmap()
00258 {
00259 if (image != NULL)
00260 {
00261 BITMAPINFO bmi;
00262 ZeroMemory(&bmi, sizeof(bmi));
00263 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00264 bmi.bmiHeader.biWidth = image->getWidth();
00265 bmi.bmiHeader.biHeight = image->getHeight();
00266 bmi.bmiHeader.biPlanes = 1;
00267 bmi.bmiHeader.biBitCount = 32;
00268 bmi.bmiHeader.biCompression = BI_RGB;
00269 bmi.bmiHeader.biSizeImage = image->getWidth() * image->getHeight() * 4;
00270
00271 HDC hwndDC = GetDC(hwnd);
00272 HDC hDC = CreateCompatibleDC(hwndDC);
00273
00274 void* bmPixels = NULL;
00275
00276
00277 hBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &bmPixels, NULL, 0x0);
00278
00279
00280
00281
00282 if (bmPixels != NULL)
00283 {
00284 unsigned char* src = image->getPixels();
00285 unsigned char* dst = reinterpret_cast<unsigned char*>(bmPixels);
00286
00287 for (unsigned int i = 0; i < (unsigned int) image->getHeight(); i++)
00288 {
00289 for (unsigned int j = 0; j < (unsigned int) image->getWidth(); j++)
00290 {
00291 unsigned char* srcPix = &src[4 * (image->getWidth() * (image->getHeight() - i - 1) + j)];
00292 unsigned char* dstPix = &dst[4 * (image->getWidth() * i + j)];
00293
00294
00295 unsigned int alpha = srcPix[3];
00296 dstPix[0] = (unsigned char) ((srcPix[2] * alpha) / 255);
00297 dstPix[1] = (unsigned char) ((srcPix[1] * alpha) / 255);
00298 dstPix[2] = (unsigned char) ((srcPix[0] * alpha) / 255);
00299 dstPix[3] = srcPix[3];
00300 }
00301 }
00302 }
00303
00304 DeleteDC(hDC);
00305
00306
00307
00308 if (hBitmap)
00309 {
00310 hCompositionBitmap = CreateCompatibleBitmap(hwndDC, image->getWidth(), image->getHeight());
00311 }
00312 }
00313
00314 return hBitmap != 0 && hCompositionBitmap != 0;
00315 }
00316
00317
00318 int SplashWindow::messageLoop()
00319 {
00320 if (!hwnd)
00321 showSplash();
00322
00323 MSG msg;
00324 while (GetMessage(&msg, NULL, 0, 0))
00325 {
00326 TranslateMessage(&msg);
00327 DispatchMessage(&msg);
00328 }
00329
00330 return msg.wParam ;
00331 }
00332
00333
00334
00335 void SplashWindow::setMessage(const string& msg)
00336 {
00337 message = msg;
00338 InvalidateRect(hwnd, NULL, FALSE);
00339 updateWindow();
00340 }
00341
00342
00343 void SplashWindow::showSplash()
00344 {
00345 close();
00346 createWindow();
00347 }
00348
00349
00350 int SplashWindow::close()
00351 {
00352
00353 if (hwnd)
00354 {
00355 DestroyWindow(hwnd);
00356 hwnd = 0;
00357 UnregisterClass(className, ::GetModuleHandle(NULL));
00358 return 1;
00359 }
00360
00361 return 0;
00362 }