386 lines
11 KiB
C++
386 lines
11 KiB
C++
|
/* Copyright 1997 Microsoft */
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include "resource.h"
|
||
|
|
||
|
#include <mluisupp.h>
|
||
|
|
||
|
#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 );
|
||
|
}
|