/* Splash Screen Plugin for Miranda-IM (www.miranda-im.org) (c) 2004-2007 nullbie, (c) 2005-2007 Thief This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA File name : $URL: http://svn.miranda.im/mainrepo/splashscreen/trunk/src/splash.cpp $ Revision : $Rev: 1585 $ Last change on : $Date: 2010-04-09 12:13:29 +0300 (Пт, 09 апр 2010) $ Last change by : $Author: ghazan $ */ #include "headers.h" #include "splash.h" bool ShowSplash(bool bpreview) { if (bpreview && bpreviewruns) return 0; if (bpreview) bpreviewruns = true; unsigned long timeout = 0; SplashBmp = new MyBitmap; #ifdef _DEBUG logMessage("Loading splash file", szSplashFile); #endif SplashBmp->loadFromFile(szSplashFile, NULL); DWORD threadID; #ifdef _DEBUG logMessage("Thread","start"); #endif if (bpreview) { ShowWindow(hwndSplash, SW_HIDE); DestroyWindow(hwndSplash); timeout = 2000; #ifdef _DEBUG logMessage("Preview","yes"); #endif } else { timeout = options.showtime; #ifdef _DEBUG char b [40]; sprintf(b,"%d",options.showtime); logMessage("Timeout",b); #endif } hSplashThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SplashThread, (LPVOID)timeout, 0, &threadID); #ifdef _DEBUG logMessage("Thread","end"); #endif CloseHandle(hSplashThread); hSplashThread = NULL; return 1; } LRESULT CALLBACK SplashWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_LOADED: { #ifdef _DEBUG logMessage("WM_LOADED","called"); #endif if (!MyUpdateLayeredWindow) ShowWindow(hwndSplash, SW_SHOWNORMAL); if (!options.showtime) SetTimer(hwnd, 7, 2000, 0); break; } case WM_LBUTTONDOWN: PostMessage(hwnd, WM_CLOSE, 0, 0); break; case WM_TIMER: #ifdef _DEBUG char b [40]; sprintf(b,"%d",wParam); logMessage("Timer ID",b); sprintf(b,"%d",options.showtime); logMessage("ShowTime value",b); #endif if (options.showtime > 0) //TimeToShow enabled { if (wParam == 6) { PostMessage(hwnd, WM_CLOSE, 0, 0); #ifdef _DEBUG logMessage("Showtime timer","triggered"); #endif } } else { PostMessage(hwnd, WM_CLOSE, 0, 0); if (wParam == 7) { #ifdef _DEBUG logMessage("On Modules Loaded timer","triggered"); #endif } if (wParam == 8) { #ifdef _DEBUG logMessage("On Modules Loaded workaround","triggered"); #endif } } break; case WM_RBUTTONDOWN: { ShowWindow(hwndSplash, SW_HIDE); DestroyWindow(hwndSplash); bpreviewruns = false; // preview is stopped. break; } case WM_CLOSE: { if (MyUpdateLayeredWindow) // Win 2000+ { RECT rc; GetWindowRect(hwndSplash, &rc); POINT ptDst = { rc.left, rc.top }; POINT ptSrc = { 0, 0 }; SIZE sz = { rc.right - rc.left, rc.bottom - rc.top }; BLENDFUNCTION blend; blend.BlendOp = AC_SRC_OVER; blend.BlendFlags = 0; blend.SourceConstantAlpha = 255; blend.AlphaFormat = AC_SRC_ALPHA; // Fade Out if (options.fadeout) { int i; for (i = 255; i>=0; i -= options.fosteps) { blend.SourceConstantAlpha = i; MyUpdateLayeredWindow(hwndSplash, NULL, &ptDst, &sz, SplashBmp->getDC(), &ptSrc, 0xffffffff, &blend, LWA_ALPHA); Sleep(1); } } } if (bserviceinvoked) bserviceinvoked = false; if (bpreviewruns) bpreviewruns = false; DestroyWindow(hwndSplash); } case WM_MOUSEMOVE: { if (bserviceinvoked) { PostMessage(hwnd, WM_CLOSE, 0, 0); } break; } case WM_DESTROY: { PostQuitMessage(0); #ifdef _DEBUG logMessage("WM_DESTROY","called"); #endif break; } case WM_PAINT: { if (!MyUpdateLayeredWindow) // Win 9x { #ifdef _DEBUG logMessage("WM_PAINT","painting.."); #endif PAINTSTRUCT ps; BeginPaint(hwndSplash, &ps); BitBlt(ps.hdc, 0, 0, SplashBmp->getWidth(), SplashBmp->getHeight(), tmpBmp->getDC(), 0, 0, SRCCOPY); EndPaint(hwndSplash, &ps); } break; } ShowWindow(hwndSplash, SW_HIDE); DestroyWindow(hwndSplash); break; } return DefWindowProc(hwnd, message, wParam, lParam); } int SplashThread(void *arg) { // Old code, doesn't support mp3 files if (options.playsnd) PlaySound(szSoundFile, NULL, SND_ASYNC | SND_FILENAME | SND_NOWAIT); /* // Buggy code, dropped for now if (options.playsnd) { char cmd[32] = "play"; // TODO: figure out if this is working. if(options.loopsnd) strcat(cmd, " repeat"); #ifdef _DEBUG logMessage("Command",cmd); #endif if(strlen(szSoundFile) && (mciWnd = MCIWndCreate(NULL, 0, MCIWNDF_NOPLAYBAR, szSoundFile)) != NULL) { SetWindowPos(mciWnd,HWND_BOTTOM,-1000,-1000,0,0,SWP_NOSIZE); ShowWindow(mciWnd, SW_HIDE); if(MCIWndCanPlay(mciWnd)) MCIWndSendString(mciWnd, cmd); } } */ WNDCLASSEX wcl; wcl.cbSize = sizeof(wcl); wcl.lpfnWndProc = SplashWindowProc; wcl.style = 0; wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; wcl.hInstance = hInst; wcl.hIcon = NULL; wcl.hCursor = LoadCursor(NULL, IDC_ARROW); wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wcl.lpszMenuName = NULL; wcl.lpszClassName = SPLASH_CLASS; wcl.hIconSm = NULL; RegisterClassEx(&wcl); RECT DesktopRect; int w = GetSystemMetrics(SM_CXSCREEN); int h = GetSystemMetrics(SM_CYSCREEN); DesktopRect.left = 0; DesktopRect.top = 0; DesktopRect.right = w; DesktopRect.bottom = h; RECT WindowRect; WindowRect.left = (DesktopRect.left + DesktopRect.right - SplashBmp->getWidth()) / 2; WindowRect.top = (DesktopRect.top + DesktopRect.bottom - SplashBmp->getHeight()) / 2; WindowRect.right = WindowRect.left + SplashBmp->getWidth(); WindowRect.bottom = WindowRect.top + SplashBmp->getHeight(); hwndSplash = CreateWindowEx( WS_EX_TOOLWINDOW | WS_EX_TOPMOST,//dwStyleEx SPLASH_CLASS, //Class name NULL, //Title DS_SETFONT | DS_FIXEDSYS | WS_POPUP, //dwStyle WindowRect.left, // x WindowRect.top, // y SplashBmp->getWidth(), // Width SplashBmp->getHeight(), // Height HWND_DESKTOP, //Parent NULL, //menu handle hInst, //Instance NULL); RECT rc; GetWindowRect(hwndSplash, &rc); POINT ptDst = {rc.left, rc.top}; POINT ptSrc = {0, 0}; SIZE sz = {rc.right - rc.left, rc.bottom - rc.top}; bool splashWithMarkers = false; BLENDFUNCTION blend; blend.BlendOp = AC_SRC_OVER; blend.BlendFlags = 0; blend.SourceConstantAlpha = 0; blend.AlphaFormat = AC_SRC_ALPHA; if (options.showversion) { // locate text markers: int i, x = -1, y = -1; int splashWidth = SplashBmp->getWidth(); for (i = 0; i < splashWidth; ++i) if (SplashBmp->getRow(0)[i] & 0xFF000000) { if (x < 0) { x = i-1; // 1 pixel for marker line splashWithMarkers = true; } else { x = -1; splashWithMarkers = false; break; } } int splashHeight = SplashBmp->getHeight(); for (i = 0; splashWithMarkers && (i < splashHeight); ++i) if (SplashBmp->getRow(i)[0] & 0xFF000000) { if (y < 0) { y = i-1; // 1 pixel for marker line splashWithMarkers = true; } else { y = -1; splashWithMarkers = false; break; } } char verString[256] = {0}; //char* ptr_verString = &verString; /* if (strlen(szPrefix)) strcat(verString,(char*)szPrefix); strcat(verString,mirandaVerString); */ mir_snprintf(verString, sizeof(verString), "%s%s", szPrefix, mirandaVerString); LOGFONT lf = {0}; lf.lfHeight = 14; strcpy(lf.lfFaceName, "Verdana"); SelectObject(SplashBmp->getDC(), CreateFontIndirect(&lf)); if (!splashWithMarkers) { SIZE v_sz = {0,0}; GetTextExtentPoint32(SplashBmp->getDC(),verString,strlen(verString),&v_sz); x = SplashBmp->getWidth()/2-(v_sz.cx/2); y = SplashBmp->getHeight()-(SplashBmp->getHeight()*(100-90)/100); } SetTextColor(SplashBmp->getDC(), (0xFFFFFFFFUL-SplashBmp->getRow(y)[x])&0x00FFFFFFUL); //SplashBmp->DrawText(verString,SplashBmp->getWidth()/2-(v_sz.cx/2),SplashBmp->getHeight()-30); SetBkMode(SplashBmp->getDC(), TRANSPARENT); SplashBmp->DrawText(verString,x,y); //free (ptr_verString); } if (MyUpdateLayeredWindow) // Win 2000+ { SetWindowLong(hwndSplash, GWL_EXSTYLE, GetWindowLong(hwndSplash, GWL_EXSTYLE) | WS_EX_LAYERED); /* if (splashWithMarkers) { ++ptSrc.x; ++ptSrc.y; } */ MyUpdateLayeredWindow(hwndSplash, NULL, &ptDst, &sz, SplashBmp->getDC(), &ptSrc, 0xffffffff, &blend, LWA_ALPHA); ShowWindow(hwndSplash, SW_SHOWNORMAL); } else // Win 9x { tmpBmp = new MyBitmap(SplashBmp->getWidth(),SplashBmp->getHeight()); HDC dtDC = GetDC(GetDesktopWindow()); BitBlt(tmpBmp->getDC(), 0, 0, SplashBmp->getWidth(), SplashBmp->getHeight(), dtDC, (DesktopRect.left + DesktopRect.right - SplashBmp->getWidth()) / 2, (DesktopRect.top + DesktopRect.bottom - SplashBmp->getHeight()) / 2, SRCCOPY); ReleaseDC(GetDesktopWindow(), dtDC); tmpBmp->Blend(SplashBmp, (splashWithMarkers?-1:0), (splashWithMarkers?-1:0), SplashBmp->getWidth(), SplashBmp->getHeight()); } if (MyUpdateLayeredWindow) // Win 2000+ { if (options.fadein) { // Fade in int i; for (i = 0; i < 255; i += options.fisteps) { blend.SourceConstantAlpha = i; MyUpdateLayeredWindow(hwndSplash, NULL, &ptDst, &sz, SplashBmp->getDC(), &ptSrc, 0xffffffff, &blend, LWA_ALPHA); Sleep(1); } } blend.SourceConstantAlpha = 255; MyUpdateLayeredWindow(hwndSplash, NULL, &ptDst, &sz, SplashBmp->getDC(), &ptSrc, 0xffffffff, &blend, LWA_ALPHA); } if (DWORD(arg) > 0) { if (SetTimer(hwndSplash, 6, DWORD(arg), 0)) { #ifdef _DEBUG logMessage("Timer TimeToShow","set"); #endif } } else if (bmodulesloaded) { if (SetTimer(hwndSplash, 8, 2000, 0)) { #ifdef _DEBUG logMessage("Timer Modules loaded","set"); #endif } } // The Message Pump MSG msg; while (GetMessage(&msg, NULL, 0, 0) == TRUE) //NULL means every window in the thread; == TRUE means a safe pump. { TranslateMessage(&msg); DispatchMessage(&msg); } ExitThread(0); return 1; }