Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

385 lines
11 KiB

  1. /* Copyright 1997 Microsoft */
  2. #include "priv.h"
  3. #include "resource.h"
  4. #include <mluisupp.h>
  5. #define TIMER_TIMEOUT 1
  6. #define SPLASHWM_DISMISS WM_USER
  7. ////////////////////////////////////////////////////////////////////////////
  8. //
  9. // InitLF -- modified from comdlg32\fonts.c, used by ShowSplashScreen
  10. //
  11. // Initalize a LOGFONT structure to some base generic regular type font.
  12. //
  13. ////////////////////////////////////////////////////////////////////////////
  14. VOID InitLF(
  15. HDC hdc,
  16. LPLOGFONT lplf)
  17. {
  18. TEXTMETRIC tm;
  19. lplf->lfEscapement = 0;
  20. lplf->lfOrientation = 0;
  21. lplf->lfOutPrecision = OUT_DEFAULT_PRECIS;
  22. lplf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
  23. lplf->lfQuality = DEFAULT_QUALITY;
  24. lplf->lfPitchAndFamily = DEFAULT_PITCH;
  25. lplf->lfItalic = 0;
  26. lplf->lfWeight = FW_NORMAL;
  27. lplf->lfStrikeOut = 0;
  28. lplf->lfUnderline = 0;
  29. lplf->lfWidth = 0; // otherwise we get independant x-y scaling
  30. GetTextMetrics(hdc, &tm); // get the current textmetrics
  31. lplf->lfCharSet = tm.tmCharSet;
  32. lplf->lfFaceName[0] = 0;
  33. MLLoadString(IDS_SPLASH_FONT, lplf->lfFaceName, ARRAYSIZE(lplf->lfFaceName));
  34. TCHAR szTmp[16];
  35. MLLoadString(IDS_SPLASH_SIZE, szTmp, ARRAYSIZE(szTmp));
  36. lplf->lfHeight = StrToInt(szTmp);
  37. }
  38. BOOL g_fShown = FALSE;
  39. class CIESplashScreen : public ISplashScreen
  40. {
  41. protected:
  42. HBITMAP _hbmSplash; // The bitmap to display.
  43. HBITMAP _hbmOld;
  44. HDC _hdc;
  45. HWND _hwnd;
  46. LONG _cRef;
  47. public:
  48. CIESplashScreen( HRESULT * pHr );
  49. ~CIESplashScreen();
  50. STDMETHOD (QueryInterface)(THIS_ REFIID riid, void ** ppv);
  51. STDMETHOD_(ULONG, AddRef) ( THIS );
  52. STDMETHOD_(ULONG, Release) ( THIS );
  53. STDMETHOD ( Show ) ( HINSTANCE hinst, UINT idResHi, UINT idResLow, HWND * phwshnd );
  54. STDMETHOD ( Dismiss ) ( void );
  55. static LRESULT s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  56. BOOL _RegisterWindowClass(void);
  57. HWND ShowSplashScreen(HINSTANCE hinst, UINT idResHi, UINT idResLow);
  58. };
  59. CIESplashScreen::CIESplashScreen(HRESULT * pHr) : _cRef (1)
  60. {
  61. DllAddRef();
  62. *pHr = NOERROR;
  63. }
  64. CIESplashScreen::~CIESplashScreen()
  65. {
  66. if (_hdc)
  67. {
  68. // select the previous hbm we got when we put the splash in there,
  69. // so that we can now destroy the hbitmap
  70. SelectObject( _hdc, _hbmOld );
  71. DeleteObject(_hdc);
  72. }
  73. // destroy the hbitmpa, can only do this if we have deselected it above...
  74. if (_hbmSplash)
  75. DeleteObject(_hbmSplash);
  76. DllRelease();
  77. }
  78. STDMETHODIMP CIESplashScreen::QueryInterface (REFIID riid, void ** ppv)
  79. {
  80. HRESULT hr = NOERROR;
  81. if ( IsEqualIID( riid, IID_IUnknown ) || IsEqualIID( riid, IID_ISplashScreen ))
  82. {
  83. *ppv = SAFECAST( this, ISplashScreen *);
  84. this->AddRef();
  85. }
  86. else
  87. {
  88. hr = E_NOINTERFACE;
  89. }
  90. return hr;
  91. }
  92. STDMETHODIMP_(ULONG) CIESplashScreen::AddRef ( )
  93. {
  94. _cRef ++;
  95. return _cRef;
  96. }
  97. STDMETHODIMP_(ULONG) CIESplashScreen::Release ( )
  98. {
  99. _cRef --;
  100. if ( !_cRef )
  101. {
  102. delete this;
  103. return 0;
  104. }
  105. return _cRef;
  106. }
  107. STDMETHODIMP CIESplashScreen::Show ( HINSTANCE hinst, UINT idResHi, UINT idResLow, HWND * phwnd )
  108. {
  109. if ( !phwnd )
  110. {
  111. return E_INVALIDARG;
  112. }
  113. // First thing to do is to see if see if browser or a splash screen up...
  114. if ( g_fShown )
  115. return NULL;
  116. *phwnd = ShowSplashScreen( hinst, idResHi, idResLow );
  117. return ( *phwnd ? NOERROR : E_UNEXPECTED );
  118. }
  119. STDMETHODIMP CIESplashScreen::Dismiss ( void )
  120. {
  121. if ( _hwnd )
  122. {
  123. // Synchronously dismiss the splash screen then post a message to
  124. // destroy the window.
  125. SendMessage(_hwnd, SPLASHWM_DISMISS, 0, 0);
  126. PostMessage(_hwnd, WM_CLOSE, 0, 0);
  127. }
  128. return S_OK;
  129. }
  130. HWND CIESplashScreen::ShowSplashScreen( HINSTANCE hinst, UINT idResHi, UINT idResLow )
  131. {
  132. // don't show splash screen for IE in intergrated mode or if it's been disabled
  133. // by the admin
  134. if (
  135. ( (WhichPlatform() == PLATFORM_INTEGRATED) && (hinst == HINST_THISDLL) ) ||
  136. ( SHRestricted2(REST_NoSplash, NULL, 0) )
  137. )
  138. {
  139. return NULL;
  140. }
  141. if (!_RegisterWindowClass())
  142. return NULL;
  143. // provide default bitmap resource ID's for IE
  144. if (hinst == HINST_THISDLL)
  145. {
  146. if (idResHi == -1)
  147. idResHi = IDB_SPLASH_IEXPLORER_HI;
  148. if (idResLow == -1)
  149. idResLow = IDB_SPLASH_IEXPLORER;
  150. }
  151. // Now load the appropriate bitmap depending on colors, only use the 256 colour splash
  152. // if we are greater than 256 colours (such as 32K or 65K upwards), this will mean we don't have
  153. // to flash the palette just to put up the splash screen.
  154. _hbmSplash = (HBITMAP)LoadImage(hinst, MAKEINTRESOURCE((GetCurColorRes() > 8) ? idResHi : idResLow),
  155. IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
  156. _hdc = CreateCompatibleDC(NULL);
  157. if (!_hbmSplash || !_hdc)
  158. return NULL;
  159. // remember the old hbitmap so we can select it back before we delete the bitmap..
  160. _hbmOld = (HBITMAP) SelectObject(_hdc, _hbmSplash);
  161. // set font and color for text
  162. LOGFONT lf;
  163. HFONT hfont;
  164. HFONT hfontOld;
  165. InitLF(_hdc, &lf);
  166. hfont = CreateFontIndirect(&lf);
  167. if ( hfont == NULL ) // show the bitmap without text if we can't create the font
  168. goto Done;
  169. // select the new font and remember the old one
  170. hfontOld = (HFONT)SelectObject(_hdc, hfont);
  171. if (hfontOld)
  172. {
  173. SetTextColor(_hdc, RGB(0,0,0));
  174. SetBkColor(_hdc, RGB(255,255,255));
  175. SetBkMode(_hdc, TRANSPARENT);
  176. // draw the text on top of the selected bitmap
  177. TCHAR szText[512], szY[32];
  178. RECT rect;
  179. MLLoadString(IDS_SPLASH_Y1, szY, ARRAYSIZE(szY));
  180. MLLoadString(IDS_SPLASH_STR1, szText, ARRAYSIZE(szText));
  181. SetRect(&rect, 104, StrToInt(szY), 386, StrToInt(szY) + 10);
  182. DrawText(_hdc, szText, -1, &rect, DT_TOP | DT_LEFT | DT_SINGLELINE | DT_CALCRECT);
  183. DrawText(_hdc, szText, -1, &rect, DT_TOP | DT_LEFT | DT_SINGLELINE);
  184. MLLoadString(IDS_SPLASH_Y2, szY, ARRAYSIZE(szY));
  185. MLLoadString(IDS_SPLASH_STR2, szText, ARRAYSIZE(szText));
  186. SetRect(&rect, 104, StrToInt(szY), 386, 400);
  187. DrawText(_hdc, szText, -1, &rect, DT_TOP | DT_LEFT | DT_CALCRECT);
  188. DrawText(_hdc, szText, -1, &rect, DT_TOP | DT_LEFT);
  189. // select back the old font and delete the new one
  190. SelectObject(_hdc, hfontOld);
  191. }
  192. DeleteObject(hfont);
  193. Done:
  194. // we now have everything in the DC, ready for painting.
  195. _hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, TEXT("CIESplashScreen"), NULL,
  196. WS_OVERLAPPED | WS_CLIPCHILDREN,
  197. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  198. NULL, (HMENU)NULL, HINST_THISDLL, this);
  199. if (_hwnd)
  200. ShowWindow(_hwnd, SW_NORMAL);
  201. return _hwnd;
  202. }
  203. LRESULT CIESplashScreen::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  204. {
  205. CIESplashScreen *piess = (CIESplashScreen*)GetWindowPtr0(hwnd);
  206. if (!piess && (uMsg != WM_CREATE))
  207. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  208. switch (uMsg)
  209. {
  210. case WM_CREATE:
  211. DllAddRef(); // make sure we are not unloaded while in dialog
  212. if (lParam)
  213. {
  214. DWORD dwExStyles;
  215. piess = (CIESplashScreen*)((LPCREATESTRUCT)lParam)->lpCreateParams;
  216. SetWindowPtr0(hwnd, piess);
  217. //
  218. // Turn off mirroring for the GUI splash screen bitmap.
  219. //
  220. if ((dwExStyles=GetWindowLong(hwnd, GWL_EXSTYLE))&RTL_MIRRORED_WINDOW)
  221. {
  222. SetWindowLong(hwnd, GWL_EXSTYLE, dwExStyles&~RTL_MIRRORED_WINDOW);
  223. }
  224. // Now lets try to center the window on the screen.
  225. BITMAP bm;
  226. GetObject(piess->_hbmSplash, sizeof(bm), &bm);
  227. SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) &
  228. ~(WS_CAPTION|WS_SYSMENU|WS_BORDER|WS_THICKFRAME));
  229. SetWindowPos(hwnd, HWND_TOP,
  230. (GetSystemMetrics(SM_CXSCREEN) - bm.bmWidth) / 2,
  231. (GetSystemMetrics(SM_CYSCREEN) - bm.bmHeight) / 2,
  232. bm.bmWidth, bm.bmHeight, 0);
  233. // Set a 5 second timer to time it out.
  234. SetTimer(hwnd, TIMER_TIMEOUT, 15000, NULL);
  235. }
  236. g_fShown = TRUE;
  237. break;
  238. case WM_NCDESTROY:
  239. // the splash screen has left the building
  240. g_fShown = FALSE;
  241. DllRelease();
  242. break;
  243. case WM_ERASEBKGND:
  244. {
  245. RECT rc;
  246. GetClientRect(hwnd, &rc);
  247. HDC hdc = (HDC)wParam;
  248. BitBlt((HDC)hdc, 0, 0, rc.right, rc.bottom, piess->_hdc, 0, 0, SRCCOPY);
  249. return 1;
  250. }
  251. break;
  252. case WM_TIMER:
  253. // Now assume it is the right one.
  254. KillTimer( hwnd, TIMER_TIMEOUT );
  255. PostMessage(hwnd, WM_CLOSE, 0, 0);
  256. break;
  257. case SPLASHWM_DISMISS:
  258. // Hide ourselves and remove our reference to piess - it may be gone at any point
  259. // after this call.
  260. ShowWindow(hwnd, SW_HIDE);
  261. SetWindowPtr0(hwnd, 0);
  262. break;
  263. case WM_ACTIVATE:
  264. if ( wParam == WA_INACTIVE && hwnd != NULL )
  265. {
  266. KillTimer( hwnd, TIMER_TIMEOUT );
  267. // create a new timer for 2 seconds after loss of activation...
  268. SetTimer( hwnd, TIMER_TIMEOUT, 2000, NULL );
  269. break;
  270. }
  271. // drop through
  272. default:
  273. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  274. }
  275. return 0;
  276. }
  277. BOOL CIESplashScreen::_RegisterWindowClass(void)
  278. {
  279. WNDCLASS wc = {0};
  280. //wc.style = 0;
  281. wc.lpfnWndProc = s_WndProc ;
  282. //wc.cbClsExtra = 0;
  283. wc.cbWndExtra = sizeof(CIESplashScreen *);
  284. wc.hInstance = g_hinst ;
  285. //wc.hIcon = NULL ;
  286. //wc.hCursor = NULL;
  287. wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
  288. //wc.lpszMenuName = NULL ;
  289. wc.lpszClassName = TEXT("CIESplashScreen");
  290. return SHRegisterClass(&wc);
  291. }
  292. STDAPI CIESplashScreen_CreateInstance(IUnknown * pUnkOuter, IUnknown ** ppunk, LPCOBJECTINFO poi)
  293. {
  294. HRESULT hr = E_FAIL;
  295. CIESplashScreen * pSplash = new CIESplashScreen( & hr );
  296. if ( !pSplash )
  297. {
  298. return E_OUTOFMEMORY;
  299. }
  300. if ( FAILED( hr ))
  301. {
  302. delete pSplash;
  303. return hr;
  304. }
  305. *ppunk = SAFECAST(pSplash, ISplashScreen *);
  306. return NOERROR;
  307. }
  308. STDAPI SHCreateSplashScreen(ISplashScreen **ppSplash)
  309. {
  310. return CIESplashScreen_CreateInstance(NULL, (IUnknown **)ppSplash, NULL );
  311. }