/* Copyright 1997 Microsoft */ #include "priv.h" #include "resource.h" #include #define TIMER_TIMEOUT 1 #define SPLASHWM_DISMISS WM_USER //////////////////////////////////////////////////////////////////////////// // // InitLF -- modified from comdlg32\fonts.c, used by ShowSplashScreen // // Initalize a LOGFONT structure to some base generic regular type font. // //////////////////////////////////////////////////////////////////////////// VOID InitLF( HDC hdc, LPLOGFONT lplf) { TEXTMETRIC tm; lplf->lfEscapement = 0; lplf->lfOrientation = 0; lplf->lfOutPrecision = OUT_DEFAULT_PRECIS; lplf->lfClipPrecision = CLIP_DEFAULT_PRECIS; lplf->lfQuality = DEFAULT_QUALITY; lplf->lfPitchAndFamily = DEFAULT_PITCH; lplf->lfItalic = 0; lplf->lfWeight = FW_NORMAL; lplf->lfStrikeOut = 0; lplf->lfUnderline = 0; lplf->lfWidth = 0; // otherwise we get independant x-y scaling GetTextMetrics(hdc, &tm); // get the current textmetrics lplf->lfCharSet = tm.tmCharSet; lplf->lfFaceName[0] = 0; MLLoadString(IDS_SPLASH_FONT, lplf->lfFaceName, ARRAYSIZE(lplf->lfFaceName)); TCHAR szTmp[16]; MLLoadString(IDS_SPLASH_SIZE, szTmp, ARRAYSIZE(szTmp)); lplf->lfHeight = StrToInt(szTmp); } BOOL g_fShown = FALSE; class CIESplashScreen : public ISplashScreen { protected: HBITMAP _hbmSplash; // The bitmap to display. HBITMAP _hbmOld; HDC _hdc; HWND _hwnd; LONG _cRef; public: CIESplashScreen( HRESULT * pHr ); ~CIESplashScreen(); STDMETHOD (QueryInterface)(THIS_ REFIID riid, void ** ppv); STDMETHOD_(ULONG, AddRef) ( THIS ); STDMETHOD_(ULONG, Release) ( THIS ); STDMETHOD ( Show ) ( HINSTANCE hinst, UINT idResHi, UINT idResLow, HWND * phwshnd ); STDMETHOD ( Dismiss ) ( void ); static LRESULT s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL _RegisterWindowClass(void); HWND ShowSplashScreen(HINSTANCE hinst, UINT idResHi, UINT idResLow); }; CIESplashScreen::CIESplashScreen(HRESULT * pHr) : _cRef (1) { DllAddRef(); *pHr = NOERROR; } CIESplashScreen::~CIESplashScreen() { if (_hdc) { // select the previous hbm we got when we put the splash in there, // so that we can now destroy the hbitmap SelectObject( _hdc, _hbmOld ); DeleteObject(_hdc); } // destroy the hbitmpa, can only do this if we have deselected it above... if (_hbmSplash) DeleteObject(_hbmSplash); DllRelease(); } STDMETHODIMP CIESplashScreen::QueryInterface (REFIID riid, void ** ppv) { HRESULT hr = NOERROR; if ( IsEqualIID( riid, IID_IUnknown ) || IsEqualIID( riid, IID_ISplashScreen )) { *ppv = SAFECAST( this, ISplashScreen *); this->AddRef(); } else { hr = E_NOINTERFACE; } return hr; } STDMETHODIMP_(ULONG) CIESplashScreen::AddRef ( ) { _cRef ++; return _cRef; } STDMETHODIMP_(ULONG) CIESplashScreen::Release ( ) { _cRef --; if ( !_cRef ) { delete this; return 0; } return _cRef; } STDMETHODIMP CIESplashScreen::Show ( HINSTANCE hinst, UINT idResHi, UINT idResLow, HWND * phwnd ) { if ( !phwnd ) { return E_INVALIDARG; } // First thing to do is to see if see if browser or a splash screen up... if ( g_fShown ) return NULL; *phwnd = ShowSplashScreen( hinst, idResHi, idResLow ); return ( *phwnd ? NOERROR : E_UNEXPECTED ); } STDMETHODIMP CIESplashScreen::Dismiss ( void ) { if ( _hwnd ) { // Synchronously dismiss the splash screen then post a message to // destroy the window. SendMessage(_hwnd, SPLASHWM_DISMISS, 0, 0); PostMessage(_hwnd, WM_CLOSE, 0, 0); } return S_OK; } HWND CIESplashScreen::ShowSplashScreen( HINSTANCE hinst, UINT idResHi, UINT idResLow ) { // don't show splash screen for IE in intergrated mode or if it's been disabled // by the admin if ( ( (WhichPlatform() == PLATFORM_INTEGRATED) && (hinst == HINST_THISDLL) ) || ( SHRestricted2(REST_NoSplash, NULL, 0) ) ) { return NULL; } if (!_RegisterWindowClass()) return NULL; // provide default bitmap resource ID's for IE if (hinst == HINST_THISDLL) { if (idResHi == -1) idResHi = IDB_SPLASH_IEXPLORER_HI; if (idResLow == -1) idResLow = IDB_SPLASH_IEXPLORER; } // Now load the appropriate bitmap depending on colors, only use the 256 colour splash // if we are greater than 256 colours (such as 32K or 65K upwards), this will mean we don't have // to flash the palette just to put up the splash screen. _hbmSplash = (HBITMAP)LoadImage(hinst, MAKEINTRESOURCE((GetCurColorRes() > 8) ? idResHi : idResLow), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); _hdc = CreateCompatibleDC(NULL); if (!_hbmSplash || !_hdc) return NULL; // remember the old hbitmap so we can select it back before we delete the bitmap.. _hbmOld = (HBITMAP) SelectObject(_hdc, _hbmSplash); // set font and color for text LOGFONT lf; HFONT hfont; HFONT hfontOld; InitLF(_hdc, &lf); hfont = CreateFontIndirect(&lf); if ( hfont == NULL ) // show the bitmap without text if we can't create the font goto Done; // select the new font and remember the old one hfontOld = (HFONT)SelectObject(_hdc, hfont); if (hfontOld) { SetTextColor(_hdc, RGB(0,0,0)); SetBkColor(_hdc, RGB(255,255,255)); SetBkMode(_hdc, TRANSPARENT); // draw the text on top of the selected bitmap TCHAR szText[512], szY[32]; RECT rect; MLLoadString(IDS_SPLASH_Y1, szY, ARRAYSIZE(szY)); MLLoadString(IDS_SPLASH_STR1, szText, ARRAYSIZE(szText)); SetRect(&rect, 104, StrToInt(szY), 386, StrToInt(szY) + 10); DrawText(_hdc, szText, -1, &rect, DT_TOP | DT_LEFT | DT_SINGLELINE | DT_CALCRECT); DrawText(_hdc, szText, -1, &rect, DT_TOP | DT_LEFT | DT_SINGLELINE); MLLoadString(IDS_SPLASH_Y2, szY, ARRAYSIZE(szY)); MLLoadString(IDS_SPLASH_STR2, szText, ARRAYSIZE(szText)); SetRect(&rect, 104, StrToInt(szY), 386, 400); DrawText(_hdc, szText, -1, &rect, DT_TOP | DT_LEFT | DT_CALCRECT); DrawText(_hdc, szText, -1, &rect, DT_TOP | DT_LEFT); // select back the old font and delete the new one SelectObject(_hdc, hfontOld); } DeleteObject(hfont); Done: // we now have everything in the DC, ready for painting. _hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, TEXT("CIESplashScreen"), NULL, WS_OVERLAPPED | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, HINST_THISDLL, this); if (_hwnd) ShowWindow(_hwnd, SW_NORMAL); return _hwnd; } LRESULT CIESplashScreen::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CIESplashScreen *piess = (CIESplashScreen*)GetWindowPtr0(hwnd); if (!piess && (uMsg != WM_CREATE)) return DefWindowProc(hwnd, uMsg, wParam, lParam); switch (uMsg) { case WM_CREATE: DllAddRef(); // make sure we are not unloaded while in dialog if (lParam) { DWORD dwExStyles; piess = (CIESplashScreen*)((LPCREATESTRUCT)lParam)->lpCreateParams; SetWindowPtr0(hwnd, piess); // // Turn off mirroring for the GUI splash screen bitmap. // if ((dwExStyles=GetWindowLong(hwnd, GWL_EXSTYLE))&RTL_MIRRORED_WINDOW) { SetWindowLong(hwnd, GWL_EXSTYLE, dwExStyles&~RTL_MIRRORED_WINDOW); } // Now lets try to center the window on the screen. BITMAP bm; GetObject(piess->_hbmSplash, sizeof(bm), &bm); SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~(WS_CAPTION|WS_SYSMENU|WS_BORDER|WS_THICKFRAME)); SetWindowPos(hwnd, HWND_TOP, (GetSystemMetrics(SM_CXSCREEN) - bm.bmWidth) / 2, (GetSystemMetrics(SM_CYSCREEN) - bm.bmHeight) / 2, bm.bmWidth, bm.bmHeight, 0); // Set a 5 second timer to time it out. SetTimer(hwnd, TIMER_TIMEOUT, 15000, NULL); } g_fShown = TRUE; break; case WM_NCDESTROY: // the splash screen has left the building g_fShown = FALSE; DllRelease(); break; case WM_ERASEBKGND: { RECT rc; GetClientRect(hwnd, &rc); HDC hdc = (HDC)wParam; BitBlt((HDC)hdc, 0, 0, rc.right, rc.bottom, piess->_hdc, 0, 0, SRCCOPY); return 1; } break; case WM_TIMER: // Now assume it is the right one. KillTimer( hwnd, TIMER_TIMEOUT ); PostMessage(hwnd, WM_CLOSE, 0, 0); break; case SPLASHWM_DISMISS: // Hide ourselves and remove our reference to piess - it may be gone at any point // after this call. ShowWindow(hwnd, SW_HIDE); SetWindowPtr0(hwnd, 0); break; case WM_ACTIVATE: if ( wParam == WA_INACTIVE && hwnd != NULL ) { KillTimer( hwnd, TIMER_TIMEOUT ); // create a new timer for 2 seconds after loss of activation... SetTimer( hwnd, TIMER_TIMEOUT, 2000, NULL ); break; } // drop through default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } BOOL CIESplashScreen::_RegisterWindowClass(void) { WNDCLASS wc = {0}; //wc.style = 0; wc.lpfnWndProc = s_WndProc ; //wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(CIESplashScreen *); wc.hInstance = g_hinst ; //wc.hIcon = NULL ; //wc.hCursor = NULL; wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); //wc.lpszMenuName = NULL ; wc.lpszClassName = TEXT("CIESplashScreen"); return SHRegisterClass(&wc); } STDAPI CIESplashScreen_CreateInstance(IUnknown * pUnkOuter, IUnknown ** ppunk, LPCOBJECTINFO poi) { HRESULT hr = E_FAIL; CIESplashScreen * pSplash = new CIESplashScreen( & hr ); if ( !pSplash ) { return E_OUTOFMEMORY; } if ( FAILED( hr )) { delete pSplash; return hr; } *ppunk = SAFECAST(pSplash, ISplashScreen *); return NOERROR; } STDAPI SHCreateSplashScreen(ISplashScreen **ppSplash) { return CIESplashScreen_CreateInstance(NULL, (IUnknown **)ppSplash, NULL ); }