windows-nt/Source/XPSP1/NT/shell/shdocvw/splash.cpp
2020-09-26 16:20:57 +08:00

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 );
}