Leaked source code of windows server 2003
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.

1221 lines
35 KiB

  1. /*****************************************************************************\
  2. FILE: PreviewTh.cpp
  3. DESCRIPTION:
  4. This code will display a preview of the currently selected
  5. visual styles.
  6. BryanSt 5/5/2000
  7. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  8. \*****************************************************************************/
  9. #include "priv.h"
  10. #include "PreviewTh.h"
  11. #include "PreviewSM.h"
  12. #include "classfactory.h"
  13. // Old predef for Patterns
  14. #define CXYDESKPATTERN 8
  15. // Async Bitmap loading
  16. #define PREVIEW_PICTURE_FILENAME TEXT("PrePict.htm")
  17. #define WM_HTML_BITMAP (WM_USER + 100)
  18. #define WM_ASYNC_BITMAP (WM_HTML_BITMAP + 1)
  19. typedef struct{
  20. HWND hwnd;
  21. HBITMAP hbmp;
  22. DWORD id;
  23. WCHAR szFile[MAX_PATH];
  24. } ASYNCWALLPARAM, * PASYNCWALLPARAM;
  25. // Window Class Name
  26. #define THEMEPREV_CLASS TEXT("ThemePreview")
  27. //===========================
  28. // *** IThemePreview Interface ***
  29. //===========================
  30. extern LPCWSTR s_Icons[];
  31. HRESULT CPreviewTheme::UpdatePreview(IN IPropertyBag * pPropertyBag)
  32. {
  33. HRESULT hr = E_INVALIDARG;
  34. DEBUG_CODE(DebugStartWatch());
  35. if (pPropertyBag && _hwndPrev)
  36. {
  37. SYSTEMMETRICSALL systemMetricsAll = {0};
  38. hr = SHPropertyBag_ReadByRef(pPropertyBag, SZ_PBPROP_SYSTEM_METRICS, &systemMetricsAll, sizeof(systemMetricsAll));
  39. BOOL fSysMetDirty = (memcmp(&systemMetricsAll, &_systemMetricsAll, sizeof(SYSTEMMETRICSALL)) != 0);
  40. if (fSysMetDirty)
  41. memcpy(&_systemMetricsAll, &systemMetricsAll, sizeof(_systemMetricsAll));
  42. _putBackground(NULL, TRUE, 0);
  43. if (_fShowBack)
  44. {
  45. WCHAR szBackgroundPath[MAX_PATH];
  46. DWORD dwBackgroundTile;
  47. // See the list of Property Bag names for Themes in shpriv.idl
  48. hr = SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_BACKGROUND_PATH, szBackgroundPath, ARRAYSIZE(szBackgroundPath));
  49. hr = SHPropertyBag_ReadDWORD(pPropertyBag, SZ_PBPROP_BACKGROUND_TILE, &dwBackgroundTile);
  50. if ((lstrcmp(szBackgroundPath, _szBackgroundPath) != 0) || (_iTileMode != (int)dwBackgroundTile))
  51. {
  52. StringCchCopy(_szBackgroundPath, ARRAYSIZE(_szBackgroundPath), szBackgroundPath);
  53. _putBackground(_szBackgroundPath, FALSE, dwBackgroundTile);
  54. }
  55. }
  56. if (_fShowVS)
  57. {
  58. WCHAR szVSPath[MAX_PATH];
  59. WCHAR szVSColor[MAX_PATH];
  60. WCHAR szVSSize[MAX_PATH];
  61. hr = SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_VISUALSTYLE_PATH, szVSPath, ARRAYSIZE(szVSPath));
  62. hr = SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_VISUALSTYLE_COLOR, szVSColor, ARRAYSIZE(szVSColor));
  63. hr = SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_VISUALSTYLE_SIZE, szVSSize, ARRAYSIZE(szVSSize));
  64. if ((lstrcmp(szVSPath, _szVSPath) != 0) ||
  65. (lstrcmp(szVSColor, _szVSColor) != 0) ||
  66. (lstrcmp(szVSSize, _szVSSize) != 0) ||
  67. fSysMetDirty)
  68. {
  69. StringCchCopy(_szVSPath, ARRAYSIZE(_szVSPath), szVSPath);
  70. StringCchCopy(_szVSColor, ARRAYSIZE(_szVSColor), szVSColor);
  71. StringCchCopy(_szVSSize, ARRAYSIZE(_szVSSize), szVSSize);
  72. _putVisualStyle(_szVSPath, _szVSColor, _szVSSize, &_systemMetricsAll);
  73. }
  74. }
  75. if (_fShowIcons)
  76. {
  77. _putIcons(pPropertyBag);
  78. }
  79. }
  80. DEBUG_CODE(TraceMsg(TF_THEMEUI_PERF, "CPreviewTheme::UpdatePreview() returned %#08lx. Time=%lums", hr, DebugStopWatch()));
  81. return hr;
  82. }
  83. HRESULT CPreviewTheme::CreatePreview(IN HWND hwndParent, IN DWORD dwFlags, IN DWORD dwStyle, IN DWORD dwExStyle, IN int x, IN int y, IN int nWidth, IN int nHeight, IN IPropertyBag * pPropertyBag, IN DWORD dwCtrlID)
  84. {
  85. HRESULT hr = S_OK;
  86. DEBUG_CODE(DebugStartWatch());
  87. g_bMirroredOS = IS_MIRRORING_ENABLED();
  88. _fRTL = IS_WINDOW_RTL_MIRRORED(hwndParent);
  89. _hwndPrev = CreateWindowEx(dwExStyle, THEMEPREV_CLASS, L"Preview", dwStyle, x, y, nWidth, nHeight, hwndParent, (HMENU)IntToPtr(dwCtrlID), HINST_THISDLL, NULL);
  90. if (_hwndPrev)
  91. {
  92. SetWindowLongPtr(_hwndPrev, GWLP_USERDATA, (LONG_PTR)this);
  93. if (_pThumb)
  94. _pThumb->Init(_hwndPrev, WM_HTML_BITMAP);
  95. GetClientRect(_hwndPrev, &_rcOuter);
  96. if (dwFlags & TMPREV_SHOWMONITOR)
  97. {
  98. _fShowMon = TRUE;
  99. BITMAP bmMon;
  100. GetObject(_hbmMon, sizeof(bmMon), &bmMon);
  101. int ox = (RECTWIDTH(_rcOuter) - bmMon.bmWidth) / 2;
  102. int oy = (RECTHEIGHT(_rcOuter) - bmMon.bmHeight) / 2;
  103. RECT rc = { 16 + ox, 17 + oy, 168 + ox, 129 + oy};
  104. _rcInner = rc;
  105. _cxMon = ox;
  106. _cyMon = oy;
  107. }
  108. else
  109. {
  110. _rcInner = _rcOuter;
  111. }
  112. HDC hdcTemp = GetDC(_hwndPrev);
  113. if (hdcTemp)
  114. {
  115. HBITMAP hbmMem = CreateCompatibleBitmap(hdcTemp, RECTWIDTH(_rcOuter), RECTHEIGHT(_rcOuter));
  116. if (hbmMem)
  117. {
  118. HBITMAP hbmOld = (HBITMAP) SelectObject(_hdcMem, hbmMem);
  119. DeleteObject(hbmOld);
  120. }
  121. else
  122. hr = E_FAIL;
  123. ReleaseDC(_hwndPrev, hdcTemp);
  124. }
  125. else
  126. hr = E_FAIL;
  127. if (dwFlags & TMPREV_SHOWBKGND)
  128. {
  129. _fShowBack = TRUE;
  130. }
  131. _fShowVS = dwFlags & TMPREV_SHOWVS;
  132. _fOnlyActiveWindow = _fShowIcons = dwFlags & TMPREV_SHOWICONS;
  133. DEBUG_CODE(TraceMsg(TF_THEMEUI_PERF, "CPreviewTheme::CreatePreview() returned %#08lx. Time=%lums", hr, DebugStopWatch()));
  134. if (SUCCEEDED(hr))
  135. hr = UpdatePreview(pPropertyBag);
  136. }
  137. return hr;
  138. }
  139. //===========================
  140. // *** IUnknown Interface ***
  141. //===========================
  142. ULONG CPreviewTheme::AddRef()
  143. {
  144. return InterlockedIncrement(&m_cRef);
  145. }
  146. ULONG CPreviewTheme::Release()
  147. {
  148. ASSERT( 0 != m_cRef );
  149. ULONG cRef = InterlockedDecrement(&m_cRef);
  150. if ( 0 == cRef )
  151. {
  152. delete this;
  153. }
  154. return cRef;
  155. }
  156. HRESULT CPreviewTheme::QueryInterface(REFIID riid, void **ppvObj)
  157. {
  158. static const QITAB qit[] =
  159. {
  160. QITABENT(CPreviewTheme, IObjectWithSite),
  161. QITABENT(CPreviewTheme, IThemePreview),
  162. { 0 },
  163. };
  164. return QISearch(this, qit, riid, ppvObj);
  165. }
  166. //===========================
  167. // *** Class Methods ***
  168. //===========================
  169. CPreviewTheme::CPreviewTheme() : m_cRef(1)
  170. {
  171. DllAddRef();
  172. // This needs to be allocated in Zero Inited Memory.
  173. // Assert that all Member Variables are inited to Zero.
  174. ASSERT(!m_pTheme);
  175. ASSERT(!m_pScheme);
  176. ASSERT(!m_pStyle);
  177. ASSERT(!m_pSize);
  178. ASSERT(!_hwndPrev);
  179. }
  180. HRESULT CPreviewTheme::_Init(void)
  181. {
  182. HRESULT hr = S_OK;
  183. _RegisterThemePreviewClass(HINST_THISDLL);
  184. HDC hdc = GetDC(NULL);
  185. if (hdc)
  186. {
  187. _hdcMem = CreateCompatibleDC(hdc);
  188. ReleaseDC(NULL, hdc);
  189. }
  190. else
  191. hr = E_FAIL;
  192. if (_hdcMem)
  193. {
  194. _hbmMon = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(IDB_MONITOR));
  195. if (_hbmMon)
  196. {
  197. if (LoadString(HINST_THISDLL, IDS_NONE, _szNone, ARRAYSIZE(_szNone)) == 0)
  198. hr = E_FAIL;
  199. }
  200. else
  201. hr = E_FAIL;
  202. if (SUCCEEDED(hr))
  203. hr = CoCreateInstance(CLSID_Thumbnail, NULL, CLSCTX_INPROC_SERVER, IID_IThumbnail, (void **)&_pThumb);
  204. }
  205. else
  206. hr = E_FAIL;
  207. if (FAILED(hr))
  208. {
  209. if (_hbmMon)
  210. {
  211. DeleteObject(_hbmMon);
  212. _hbmMon = NULL;
  213. }
  214. if (_hdcMem)
  215. {
  216. DeleteDC(_hdcMem);
  217. _hdcMem = NULL;
  218. }
  219. }
  220. return hr;
  221. }
  222. CPreviewTheme::~CPreviewTheme()
  223. {
  224. if (_hwndPrev && IsWindow(_hwndPrev))
  225. {
  226. DestroyWindow(_hwndPrev);
  227. _hwndPrev = NULL;
  228. }
  229. if (_hbmMon)
  230. {
  231. DeleteObject(_hbmMon);
  232. _hbmMon = NULL;
  233. }
  234. if (_hbmBack)
  235. {
  236. DeleteObject(_hbmBack);
  237. _hbmBack = NULL;
  238. }
  239. if (_hbrBack)
  240. {
  241. DeleteObject(_hbrBack);
  242. _hbrBack = NULL;
  243. }
  244. if (_hbmVS)
  245. {
  246. DeleteObject(_hbmVS);
  247. }
  248. if (_hdcMem)
  249. {
  250. DeleteDC(_hdcMem);
  251. _hpalMem = NULL;
  252. _hdcMem = NULL;
  253. }
  254. if (_pActiveDesk)
  255. {
  256. _pActiveDesk->Release();
  257. }
  258. for (int i = 0; i < MAX_PREVIEW_ICONS; i++)
  259. {
  260. if (_iconList[i].hicon)
  261. {
  262. DestroyIcon(_iconList[i].hicon);
  263. }
  264. }
  265. ATOMICRELEASE(m_pTheme);
  266. ATOMICRELEASE(m_pScheme);
  267. ATOMICRELEASE(m_pStyle);
  268. ATOMICRELEASE(m_pSize);
  269. ATOMICRELEASE(_pThumb);
  270. DllRelease();
  271. }
  272. LRESULT CALLBACK CPreviewTheme::ThemePreviewWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  273. {
  274. CPreviewTheme * pThis = (CPreviewTheme *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  275. if (pThis)
  276. return pThis->_ThemePreviewWndProc(hWnd, wMsg, wParam, lParam);
  277. return DefWindowProc(hWnd, wMsg, wParam, lParam);
  278. }
  279. LRESULT CPreviewTheme::_ThemePreviewWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  280. {
  281. switch(wMsg)
  282. {
  283. case WM_CREATE:
  284. break;
  285. case WM_DESTROY:
  286. {
  287. MSG msg;
  288. while (PeekMessage(&msg, hWnd, WM_HTML_BITMAP, WM_ASYNC_BITMAP, PM_REMOVE))
  289. {
  290. if ( msg.lParam )
  291. {
  292. if (msg.message == WM_ASYNC_BITMAP)
  293. {
  294. // clean up this useless stuff
  295. DeleteObject(((PASYNCWALLPARAM)(msg.lParam))->hbmp);
  296. LocalFree((PASYNCWALLPARAM)(msg.lParam));
  297. }
  298. else // WM_HTML_BITMAP
  299. DeleteObject((HBITMAP)msg.lParam);
  300. }
  301. }
  302. }
  303. break;
  304. case WM_PALETTECHANGED:
  305. break;
  306. case WM_QUERYNEWPALETTE:
  307. break;
  308. case WM_HTML_BITMAP:
  309. {
  310. // may come through with NULL if the image extraction failed....
  311. if (wParam == _dwWallpaperID && lParam)
  312. {
  313. _fHTMLBitmap = TRUE;
  314. _iTileMode = _iNewTileMode;
  315. _putBackgroundBitmap((HBITMAP)lParam);
  316. // Take ownership of bitmap
  317. return 1;
  318. }
  319. // Bitmap for something no longer selected
  320. return 0;
  321. }
  322. case WM_ASYNC_BITMAP:
  323. if (lParam)
  324. {
  325. PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) lParam;
  326. ASSERT(pawp->hbmp);
  327. if (pawp->id == _dwWallpaperID)
  328. {
  329. _fHTMLBitmap = FALSE;
  330. _iTileMode = _iNewTileMode;
  331. _putBackgroundBitmap(pawp->hbmp);
  332. }
  333. else
  334. {
  335. // clean up this useless stuff
  336. DeleteObject(pawp->hbmp);
  337. LocalFree(pawp);
  338. }
  339. }
  340. break;
  341. case WM_PAINT:
  342. {
  343. PAINTSTRUCT ps;
  344. BeginPaint(hWnd, &ps);
  345. _Paint(ps.hdc);
  346. EndPaint(hWnd, &ps);
  347. }
  348. return 0;
  349. case WM_ERASEBKGND:
  350. _Paint((HDC)wParam);
  351. return 1;
  352. }
  353. return DefWindowProc(hWnd,wMsg,wParam,lParam);
  354. }
  355. BOOL CPreviewTheme::_RegisterThemePreviewClass(HINSTANCE hInst)
  356. {
  357. WNDCLASS wc;
  358. if (!GetClassInfo(hInst, THEMEPREV_CLASS, &wc)) {
  359. wc.style = 0;
  360. wc.lpfnWndProc = CPreviewTheme::ThemePreviewWndProc;
  361. wc.cbClsExtra = 0;
  362. wc.cbWndExtra = 0;
  363. wc.hInstance = hInst;
  364. wc.hIcon = NULL;
  365. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  366. wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
  367. wc.lpszMenuName = NULL;
  368. wc.lpszClassName = THEMEPREV_CLASS;
  369. if (!RegisterClass(&wc))
  370. return FALSE;
  371. }
  372. return TRUE;
  373. }
  374. HRESULT CPreviewTheme::_putIcons(IPropertyBag* pPropertyBag)
  375. {
  376. HRESULT hr;
  377. for (int i = 0; i < MAX_PREVIEW_ICONS; i++)
  378. {
  379. if (_iconList[i].hicon)
  380. {
  381. DestroyIcon(_iconList[i].hicon);
  382. }
  383. WCHAR szIcon[MAX_PATH];
  384. hr = SHPropertyBag_ReadStr(pPropertyBag, s_Icons[i], szIcon, ARRAYSIZE(szIcon));
  385. if (SUCCEEDED(hr))
  386. {
  387. WCHAR szIconModule[MAX_PATH];
  388. SHExpandEnvironmentStrings(szIcon, szIconModule, ARRAYSIZE(szIconModule));
  389. int iIndex = PathParseIconLocation(szIconModule);
  390. ExtractIconEx(szIconModule, iIndex, &_iconList[i].hicon, NULL, 1);
  391. }
  392. }
  393. _fMemIsDirty = TRUE;
  394. InvalidateRect(_hwndPrev, &_rcInner, FALSE);
  395. return S_OK;
  396. }
  397. HRESULT CPreviewTheme::_putVisualStyle(LPCWSTR pszVSPath, LPCWSTR pszVSColor, LPCWSTR pszVSSize, SYSTEMMETRICSALL* psysMet)
  398. {
  399. HRESULT hr = E_FAIL;
  400. HBITMAP hbmVS = NULL;
  401. HBITMAP hbmOldVS = NULL;
  402. HDC hdcVS = NULL;
  403. if (!pszVSPath || !*pszVSPath)
  404. {
  405. HDC hdcTemp = GetDC(_hwndPrev);
  406. if (hdcTemp)
  407. {
  408. hdcVS = CreateCompatibleDC(hdcTemp);
  409. hbmVS = CreateCompatibleBitmap(hdcTemp, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner));
  410. hbmOldVS = (HBITMAP)SelectObject(hdcVS, hbmVS);
  411. if (hdcVS && hbmVS)
  412. {
  413. RECT rcVS;
  414. rcVS.left = 0;
  415. rcVS.right = RECTWIDTH(_rcInner) - (_fShowIcons ? 100 : 8);
  416. rcVS.top = 0;
  417. rcVS.bottom = RECTHEIGHT(_rcInner) - (_fShowIcons ? 50 : 8);
  418. // Create everyone including globals
  419. HDC hdcVStemp = CreateCompatibleDC(hdcTemp);
  420. HBITMAP hbmVStemp = CreateCompatibleBitmap(hdcTemp, RECTWIDTH(rcVS), RECTHEIGHT(rcVS));
  421. HBITMAP hbmOldVStemp = (HBITMAP) SelectObject(hdcVStemp, hbmVStemp);
  422. if (hdcVStemp && hbmVStemp)
  423. {
  424. if (_fRTL)
  425. {
  426. SetLayout(hdcVStemp, LAYOUT_RTL);
  427. SetLayout(hdcVS, LAYOUT_RTL);
  428. }
  429. HBRUSH hbr = CreateSolidBrush(RGB(255, 255, 0));
  430. if (hbr)
  431. {
  432. FillRect(hdcVStemp, &rcVS, hbr);
  433. RECT rcTemp = {0, 0, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner)};
  434. FillRect(hdcVS, &rcTemp, hbr);
  435. DeleteObject(hbr);
  436. }
  437. // Render image at full size
  438. hr = DrawAppearance(hdcVStemp, &rcVS, psysMet, _fOnlyActiveWindow, _fRTL);
  439. // Shrink image to fit on "monitor"
  440. int iX = _rcInner.left + (_fShowIcons ? 10 : RECTWIDTH(_rcInner) - RECTWIDTH(rcVS));
  441. BitBlt(hdcVS, iX, _rcInner.top, RECTWIDTH(rcVS), RECTHEIGHT(rcVS),
  442. hdcVStemp, rcVS.left, rcVS.top, SRCCOPY);
  443. }
  444. // Free temporary variables and store off globals
  445. if (hdcVStemp)
  446. {
  447. SelectObject(hdcVStemp, hbmOldVStemp);
  448. DeleteDC(hdcVStemp);
  449. }
  450. if (hbmVStemp)
  451. {
  452. DeleteObject(hbmVStemp);
  453. }
  454. }
  455. ReleaseDC(_hwndPrev, hdcTemp);
  456. }
  457. else
  458. hr = E_OUTOFMEMORY;
  459. }
  460. else
  461. {
  462. hr = S_OK;
  463. }
  464. if (SUCCEEDED(hr))
  465. {
  466. if (_hbmVS)
  467. {
  468. DeleteObject(_hbmVS);
  469. }
  470. _hbmVS = hbmVS;
  471. hbmVS = NULL;
  472. _fMemIsDirty = TRUE;
  473. InvalidateRect(_hwndPrev, &_rcInner, FALSE);
  474. }
  475. if (hdcVS)
  476. {
  477. if (hbmOldVS)
  478. {
  479. SelectObject(hdcVS, hbmOldVS);
  480. }
  481. DeleteDC(hdcVS);
  482. }
  483. if (hbmVS)
  484. {
  485. DeleteObject(hbmVS);
  486. }
  487. return hr;
  488. }
  489. HRESULT CPreviewTheme::_putBackgroundBitmap(HBITMAP hbm)
  490. {
  491. if (_hbmBack)
  492. {
  493. DeleteObject(_hbmBack);
  494. _hbmBack = NULL;
  495. }
  496. if (_hpalMem)
  497. {
  498. DeleteObject(_hpalMem);
  499. _hpalMem = NULL;
  500. }
  501. _hbmBack = hbm;
  502. if (_hbmBack)
  503. {
  504. BITMAP bm;
  505. GetObject(_hbmBack, sizeof(bm), &bm);
  506. if (GetDeviceCaps(_hdcMem, RASTERCAPS) & RC_PALETTE)
  507. {
  508. if (bm.bmBitsPixel * bm.bmPlanes > 8)
  509. _hpalMem = CreateHalftonePalette(_hdcMem);
  510. else if (bm.bmBitsPixel * bm.bmPlanes == 8)
  511. _PaletteFromDS(_hdcMem, &_hpalMem);
  512. else
  513. _hpalMem = NULL; //!!! assume 1 or 4bpp images dont have palettes
  514. }
  515. }
  516. _fMemIsDirty = TRUE;
  517. InvalidateRect(_hwndPrev, &_rcInner, FALSE);
  518. return S_OK;
  519. }
  520. HRESULT CPreviewTheme::_putBackground(BSTR bstrBackground, BOOL fPattern, int iTileMode)
  521. {
  522. if (fPattern)
  523. {
  524. TCHAR szBuf[MAX_PATH];
  525. // get rid of old brush if there was one
  526. if (_hbrBack)
  527. DeleteObject(_hbrBack);
  528. if (bstrBackground && lstrcmpi(bstrBackground, _szNone))
  529. {
  530. WORD patbits[CXYDESKPATTERN] = {0, 0, 0, 0, 0, 0, 0, 0};
  531. if (GetPrivateProfileString(TEXT("patterns"), bstrBackground, TEXT(""),
  532. szBuf, ARRAYSIZE(szBuf), TEXT("control.ini")))
  533. {
  534. _ReadPattern(szBuf, patbits);
  535. }
  536. HBITMAP hbmTemp = CreateBitmap(8, 8, 1, 1, patbits);
  537. if (hbmTemp)
  538. {
  539. _hbrBack = CreatePatternBrush(hbmTemp);
  540. DeleteObject(hbmTemp);
  541. }
  542. }
  543. else
  544. {
  545. _hbrBack = CreateSolidBrush(_systemMetricsAll.schemeData.rgb[COLOR_BACKGROUND]);
  546. }
  547. if (!_hbrBack)
  548. _hbrBack = (HBRUSH) GetStockObject(BLACK_BRUSH);
  549. _fMemIsDirty = TRUE;
  550. InvalidateRect(_hwndPrev, &_rcInner, FALSE);
  551. }
  552. else
  553. {
  554. _iNewTileMode = iTileMode;
  555. return _GetWallpaperAsync(bstrBackground);
  556. }
  557. return S_OK;
  558. }
  559. /*-------------------------------------------------------------
  560. ** given a pattern string from an ini file, return the pattern
  561. ** in a binary (ie useful) form.
  562. **-------------------------------------------------------------*/
  563. HRESULT CPreviewTheme::_ReadPattern(LPTSTR lpStr, WORD FAR *patbits)
  564. {
  565. short i, val;
  566. /* Get eight groups of numbers seprated by non-numeric characters. */
  567. for (i = 0; i < CXYDESKPATTERN; i++)
  568. {
  569. val = 0;
  570. if (*lpStr != TEXT('\0'))
  571. {
  572. /* Skip over any non-numeric characters. */
  573. while (!(*lpStr >= TEXT('0') && *lpStr <= TEXT('9')))
  574. lpStr++;
  575. /* Get the next series of digits. */
  576. while (*lpStr >= TEXT('0') && *lpStr <= TEXT('9'))
  577. val = val*10 + *lpStr++ - TEXT('0');
  578. }
  579. patbits[i] = val;
  580. }
  581. return S_OK;
  582. }
  583. /*----------------------------------------------------------------------------*\
  584. \*----------------------------------------------------------------------------*/
  585. HRESULT CPreviewTheme::_PaletteFromDS(HDC hdc, HPALETTE* phPalette)
  586. {
  587. DWORD adw[257];
  588. int i,n;
  589. n = GetDIBColorTable(hdc, 0, 256, (LPRGBQUAD)&adw[1]);
  590. adw[0] = MAKELONG(0x300, n);
  591. for (i=1; i<=n; i++)
  592. adw[i] = RGB(GetBValue(adw[i]),GetGValue(adw[i]),GetRValue(adw[i]));
  593. *phPalette = (n == 0) ? NULL : CreatePalette((LPLOGPALETTE)&adw[0]);
  594. return S_OK;
  595. }
  596. HRESULT CPreviewTheme::_DrawMonitor(HDC hdc)
  597. {
  598. HBITMAP hbmT;
  599. HDC hdcMon;
  600. BITMAP bmMon;
  601. if (_hbmMon == NULL)
  602. {
  603. return E_OUTOFMEMORY;
  604. }
  605. //
  606. // convert the "base" of the monitor to the right color.
  607. //
  608. // the lower left of the bitmap has a transparent color
  609. // we fixup using FloodFill
  610. //
  611. hdcMon = CreateCompatibleDC(NULL);
  612. if (hdcMon)
  613. {
  614. hbmT = (HBITMAP) SelectObject(hdcMon, _hbmMon);
  615. GetObject(_hbmMon, sizeof(bmMon), &bmMon);
  616. FillRect(hdc, &_rcOuter, GetSysColorBrush(COLOR_3DFACE));
  617. DrawThemeParentBackground(_hwndPrev, hdc, NULL);
  618. TransparentBlt(hdc, _rcOuter.left + _cxMon, _rcOuter.top + _cyMon, bmMon.bmWidth, bmMon.bmHeight,
  619. hdcMon, 0, 0, bmMon.bmWidth, bmMon.bmHeight, RGB(255, 0, 255));
  620. // clean up after ourselves
  621. SelectObject(hdcMon, hbmT);
  622. DeleteDC(hdcMon);
  623. }
  624. return S_OK;
  625. }
  626. HRESULT CPreviewTheme::_DrawBackground(HDC hdc)
  627. {
  628. // Draw Pattern first
  629. if (_hbrBack)
  630. {
  631. COLORREF clrOldText = SetTextColor(hdc, GetSysColor(COLOR_BACKGROUND));
  632. COLORREF clrOldBk = SetBkColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  633. HBRUSH hbr = (HBRUSH) SelectObject(hdc, _hbrBack);
  634. PatBlt(hdc, _rcInner.left, _rcInner.top, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner), PATCOPY);
  635. SelectObject(hdc, hbr);
  636. SetTextColor(hdc, clrOldText);
  637. SetBkColor(hdc, clrOldBk);
  638. }
  639. /// Start Draw Wall Paper
  640. if (_hbmBack && _fShowBack)
  641. {
  642. HDC hdcBack = CreateCompatibleDC(hdc);
  643. if (hdcBack)
  644. {
  645. HBITMAP hbmOldBack = (HBITMAP)SelectObject(hdcBack, _hbmBack);
  646. BITMAP bm;
  647. GetObject(_hbmBack, sizeof(bm), &bm);
  648. int dxBack = MulDiv(bm.bmWidth, RECTWIDTH(_rcInner), GetDeviceCaps(hdc, HORZRES));
  649. int dyBack = MulDiv(bm.bmHeight, RECTHEIGHT(_rcInner), GetDeviceCaps(hdc, VERTRES));
  650. if (dxBack < 1) dxBack = 1;
  651. if (dyBack < 1) dyBack = 1;
  652. if (_hpalMem)
  653. {
  654. SelectPalette(hdc, _hpalMem, TRUE);
  655. RealizePalette(hdc);
  656. }
  657. IntersectClipRect(hdc, _rcInner.left, _rcInner.top, _rcInner.right, _rcInner.bottom);
  658. SetStretchBltMode(hdc, COLORONCOLOR);
  659. if ((_iTileMode == WPSTYLE_TILE) && (!_fHTMLBitmap))
  660. {
  661. int i;
  662. StretchBlt(hdc, _rcInner.left, _rcInner.top, dxBack, dyBack,
  663. hdcBack, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  664. for (i = _rcInner.left+dxBack; i < (_rcInner.left + RECTWIDTH(_rcInner)); i+= dxBack)
  665. BitBlt(hdc, i, _rcInner.top, dxBack, dyBack, hdc, _rcInner.left, _rcInner.top, SRCCOPY);
  666. for (i = _rcInner.top; i < (_rcInner.top + RECTHEIGHT(_rcInner)); i += dyBack)
  667. BitBlt(hdc, _rcInner.left, i, RECTWIDTH(_rcInner), dyBack, hdc, _rcInner.left, _rcInner.top, SRCCOPY);
  668. }
  669. else
  670. {
  671. //We want to stretch the Bitmap to the preview monitor size ONLY for new platforms.
  672. if ((_iTileMode == WPSTYLE_STRETCH) || (_fHTMLBitmap))
  673. {
  674. //Stretch the bitmap to the whole preview monitor.
  675. dxBack = RECTWIDTH(_rcInner);
  676. dyBack = RECTHEIGHT(_rcInner);
  677. }
  678. //Center the bitmap in the preview monitor
  679. StretchBlt(hdc, _rcInner.left + (RECTWIDTH(_rcInner) - dxBack)/2, _rcInner.top + (RECTHEIGHT(_rcInner) - dyBack)/2,
  680. dxBack, dyBack, hdcBack, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  681. }
  682. // restore dc
  683. SelectPalette(hdc, (HPALETTE) GetStockObject(DEFAULT_PALETTE), TRUE);
  684. SelectClipRgn(hdc, NULL);
  685. SelectObject(hdcBack, hbmOldBack);
  686. DeleteDC(hdcBack);
  687. }
  688. }
  689. return S_OK;
  690. }
  691. HRESULT CPreviewTheme::_DrawVisualStyle(HDC hdc)
  692. {
  693. if (_hbmVS)
  694. {
  695. HDC hdcVS = CreateCompatibleDC(hdc);
  696. if (hdcVS)
  697. {
  698. HBITMAP hbmOldVS = (HBITMAP)SelectObject(hdcVS, _hbmVS);
  699. TransparentBlt(hdc, _rcInner.left, _rcInner.top, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner), hdcVS, 0, 0, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner), RGB(255, 255, 0));
  700. SelectObject(hdcVS, hbmOldVS);
  701. DeleteDC(hdcVS);
  702. }
  703. }
  704. else
  705. {
  706. RECT rc;
  707. rc.left = _fShowIcons ? 20 : 8;
  708. rc.right = RECTWIDTH(_rcInner) - (_fShowIcons ? 100 : 8);
  709. rc.top = _fShowIcons ? 10 : 8;
  710. rc.bottom = RECTHEIGHT(_rcInner) - (_fShowIcons ? 60 : 20);
  711. DrawNCPreview(hdc, NCPREV_ACTIVEWINDOW | (_fOnlyActiveWindow ? 0 : NCPREV_MESSAGEBOX | NCPREV_INACTIVEWINDOW) | (_fRTL ? NCPREV_RTL : 0) , &rc, _szVSPath, _szVSColor, _szVSSize, &(_systemMetricsAll.schemeData.ncm), (_systemMetricsAll.schemeData.rgb));
  712. }
  713. return S_OK;
  714. }
  715. HRESULT CPreviewTheme::_DrawIcons(HDC hdc)
  716. {
  717. int y = RECTHEIGHT(_rcInner) - _systemMetricsAll.nIcon - 8;
  718. int x = RECTWIDTH(_rcInner) - _systemMetricsAll.nIcon - 20;
  719. DrawIcon(hdc, x, y, _iconList[3].hicon);
  720. return S_OK;
  721. }
  722. HRESULT CPreviewTheme::_Paint(HDC hdc)
  723. {
  724. HPALETTE hpalOld = NULL;
  725. if (_fMemIsDirty)
  726. {
  727. if (_fRTL)
  728. {
  729. SetLayout(_hdcMem, LAYOUT_RTL);
  730. }
  731. // Rebuild Back Buffer
  732. if (_fShowMon)
  733. _DrawMonitor(_hdcMem);
  734. // Always draw the background, the Background switch turns the background
  735. // image on/off
  736. _DrawBackground(_hdcMem);
  737. if (_fShowIcons)
  738. _DrawIcons(_hdcMem);
  739. if (_fShowVS)
  740. _DrawVisualStyle(_hdcMem);
  741. _fMemIsDirty = FALSE;
  742. }
  743. if (_hdcMem)
  744. {
  745. if (_hpalMem)
  746. {
  747. hpalOld = SelectPalette(hdc, _hpalMem, FALSE);
  748. RealizePalette(hdc);
  749. }
  750. if (_fRTL)
  751. {
  752. SetLayout(hdc, LAYOUT_RTL);
  753. }
  754. BitBlt(hdc, _rcOuter.left, _rcOuter.top, RECTWIDTH(_rcOuter), RECTHEIGHT(_rcOuter), _hdcMem, 0, 0, SRCCOPY);
  755. if (_hpalMem)
  756. {
  757. SelectPalette(hdc, hpalOld, TRUE);
  758. RealizePalette(hdc);
  759. }
  760. }
  761. return S_OK;
  762. }
  763. DWORD CALLBACK UpdateWallProc(LPVOID pv)
  764. {
  765. ASSERT(pv);
  766. if (pv)
  767. {
  768. PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) pv;
  769. pawp->hbmp = (HBITMAP)LoadImage(NULL, pawp->szFile,
  770. IMAGE_BITMAP, 0, 0,
  771. LR_LOADFROMFILE|LR_CREATEDIBSECTION);
  772. if (pawp->hbmp)
  773. {
  774. // if all is good, then the window will handle cleaning up
  775. if (IsWindow(pawp->hwnd) && PostMessage(pawp->hwnd, WM_ASYNC_BITMAP, 0, (LPARAM)pawp))
  776. return TRUE;
  777. DeleteObject(pawp->hbmp);
  778. }
  779. LocalFree(pawp);
  780. }
  781. return TRUE;
  782. }
  783. const GUID CLSID_HtmlThumbnailExtractor = {0xeab841a0, 0x9550, 0x11cf, 0x8c, 0x16, 0x0, 0x80, 0x5f, 0x14, 0x8, 0xf3};
  784. DWORD CALLBACK UpdateWallProcHTML(LPVOID pv)
  785. {
  786. if (SUCCEEDED(CoInitialize(NULL)))
  787. {
  788. ASSERT(pv);
  789. if (pv)
  790. {
  791. PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) pv;
  792. IPersistFile *ppf;
  793. HRESULT hr = CoCreateInstance(CLSID_HtmlThumbnailExtractor, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPersistFile, &ppf));
  794. if (SUCCEEDED(hr))
  795. {
  796. hr = ppf->Load(pawp->szFile, STGM_READ);
  797. if (SUCCEEDED(hr))
  798. {
  799. IExtractImage *pei= NULL;
  800. hr = ppf->QueryInterface(IID_PPV_ARG(IExtractImage, &pei));
  801. if (SUCCEEDED(hr))
  802. {
  803. DWORD dwPriority = 0;
  804. DWORD dwFlags = IEIFLAG_SCREEN | IEIFLAG_OFFLINE;
  805. WCHAR szLocation[MAX_PATH];
  806. HDC hdc = GetDC(NULL);
  807. SIZEL rgSize = {GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES)};
  808. ReleaseDC(NULL, hdc);
  809. hr = pei->GetLocation(szLocation, ARRAYSIZE(szLocation), &dwPriority, &rgSize, SHGetCurColorRes(), &dwFlags);
  810. if (SUCCEEDED(hr))
  811. {
  812. HBITMAP hbm;
  813. hr = pei->Extract(&hbm);
  814. if (SUCCEEDED(hr))
  815. {
  816. if (!SendMessage(pawp->hwnd, WM_HTML_BITMAP, pawp->id, (LPARAM)hbm))
  817. {
  818. DeleteObject(hbm);
  819. }
  820. }
  821. }
  822. pei->Release();
  823. }
  824. }
  825. ppf->Release();
  826. }
  827. LocalFree(pawp);
  828. }
  829. CoUninitialize();
  830. }
  831. return TRUE;
  832. }
  833. //
  834. // Determines if the wallpaper can be supported in non-active desktop mode.
  835. //
  836. BOOL CPreviewTheme::_IsNormalWallpaper(LPCWSTR pszFileName)
  837. {
  838. BOOL fRet = TRUE;
  839. if (pszFileName[0] == TEXT('\0'))
  840. {
  841. fRet = TRUE;
  842. }
  843. else
  844. {
  845. LPTSTR pszExt = PathFindExtension(pszFileName);
  846. //Check for specific files that can be shown only in ActiveDesktop mode!
  847. if((lstrcmpi(pszExt, TEXT(".GIF")) == 0) ||
  848. (lstrcmpi(pszExt, TEXT(".gif")) == 0) || // 368690: Strange, but we must compare 'i' in both caps and lower case.
  849. (lstrcmpi(pszExt, TEXT(".JPG")) == 0) ||
  850. (lstrcmpi(pszExt, TEXT(".JPE")) == 0) ||
  851. (lstrcmpi(pszExt, TEXT(".JPEG")) == 0) ||
  852. (lstrcmpi(pszExt, TEXT(".PNG")) == 0) ||
  853. (lstrcmpi(pszExt, TEXT(".HTM")) == 0) ||
  854. (lstrcmpi(pszExt, TEXT(".HTML")) == 0) ||
  855. (lstrcmpi(pszExt, TEXT(".HTT")) == 0))
  856. return FALSE;
  857. //Everything else (including *.BMP files) are "normal" wallpapers
  858. }
  859. return fRet;
  860. }
  861. //
  862. // Determines if the wallpaper is a picture (vs. HTML).
  863. //
  864. BOOL CPreviewTheme::_IsWallpaperPicture(LPCWSTR pszWallpaper)
  865. {
  866. BOOL fRet = TRUE;
  867. if (pszWallpaper[0] == TEXT('\0'))
  868. {
  869. //
  870. // Empty wallpapers count as empty pictures.
  871. //
  872. fRet = TRUE;
  873. }
  874. else
  875. {
  876. LPTSTR pszExt = PathFindExtension(pszWallpaper);
  877. if ((lstrcmpi(pszExt, TEXT(".HTM")) == 0) ||
  878. (lstrcmpi(pszExt, TEXT(".HTML")) == 0) ||
  879. (lstrcmpi(pszExt, TEXT(".HTT")) == 0))
  880. {
  881. fRet = FALSE;
  882. }
  883. }
  884. return fRet;
  885. }
  886. HRESULT CPreviewTheme::_LoadWallpaperAsync(LPCWSTR pszFile, DWORD dwID, BOOL bHTML)
  887. {
  888. PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) LocalAlloc(LPTR, SIZEOF(ASYNCWALLPARAM));
  889. HRESULT hr = E_OUTOFMEMORY;
  890. if (pawp)
  891. {
  892. pawp->hwnd = _hwndPrev;
  893. pawp->id = dwID;
  894. hr = StringCchCopy(pawp->szFile, ARRAYSIZE(pawp->szFile), pszFile);
  895. if (SUCCEEDED(hr))
  896. {
  897. if (bHTML)
  898. {
  899. if (!SHQueueUserWorkItem(UpdateWallProcHTML, pawp, 0, (DWORD_PTR)0, (DWORD_PTR *)NULL, NULL, 0))
  900. {
  901. LocalFree(pawp);
  902. }
  903. }
  904. else
  905. {
  906. if (!SHQueueUserWorkItem(UpdateWallProc, pawp, 0, (DWORD_PTR)0, (DWORD_PTR *)NULL, NULL, 0))
  907. {
  908. LocalFree(pawp);
  909. }
  910. }
  911. }
  912. }
  913. return S_OK;
  914. }
  915. HRESULT CPreviewTheme::_GetWallpaperAsync(LPWSTR psz)
  916. {
  917. HRESULT hr = S_OK;
  918. WCHAR wszWallpaper[INTERNET_MAX_URL_LENGTH];
  919. LPWSTR pszWallpaper = psz;
  920. _dwWallpaperID++;
  921. if (*pszWallpaper && lstrcmpi(pszWallpaper, _szNone))
  922. {
  923. if (_IsNormalWallpaper(pszWallpaper))
  924. {
  925. _LoadWallpaperAsync(pszWallpaper, _dwWallpaperID, FALSE);
  926. }
  927. else
  928. {
  929. if(_IsWallpaperPicture(pszWallpaper))
  930. {
  931. pszWallpaper = wszWallpaper;
  932. // This is a picture (GIF, JPG etc.,)
  933. // We need to generate a small HTML file that has this picture
  934. // as the background image.
  935. //
  936. // Compute the filename for the Temporary HTML file.
  937. //
  938. GetTempPath(ARRAYSIZE(wszWallpaper), wszWallpaper);
  939. StringCchCat(wszWallpaper, ARRAYSIZE(wszWallpaper), PREVIEW_PICTURE_FILENAME);
  940. //
  941. // Generate the preview picture html file.
  942. //
  943. if (!_pActiveDesk)
  944. {
  945. hr = _GetActiveDesktop(&_pActiveDesk);
  946. }
  947. if (SUCCEEDED(hr))
  948. {
  949. _pActiveDesk->SetWallpaper(psz, 0);
  950. WALLPAPEROPT wpo = { sizeof(WALLPAPEROPT) };
  951. wpo.dwStyle = _iNewTileMode;
  952. _pActiveDesk->SetWallpaperOptions(&wpo, 0);
  953. _pActiveDesk->GenerateDesktopItemHtml(wszWallpaper, NULL, 0);
  954. }
  955. }
  956. _LoadWallpaperAsync(pszWallpaper, _dwWallpaperID, TRUE);
  957. }
  958. }
  959. else
  960. {
  961. _putBackgroundBitmap(NULL);
  962. }
  963. return hr;
  964. }
  965. HRESULT CPreviewTheme::_GetActiveDesktop(IActiveDesktop ** ppActiveDesktop)
  966. {
  967. HRESULT hr = S_OK;
  968. if (!*ppActiveDesktop)
  969. {
  970. IActiveDesktopP * piadp;
  971. if (SUCCEEDED(hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktopP, &piadp)) ))
  972. {
  973. WCHAR wszScheme[MAX_PATH];
  974. DWORD dwcch = ARRAYSIZE(wszScheme);
  975. // Get the global "edit" scheme and set ourselves us to read from and edit that scheme
  976. if (SUCCEEDED(piadp->GetScheme(wszScheme, &dwcch, SCHEME_GLOBAL | SCHEME_EDIT)))
  977. {
  978. piadp->SetScheme(wszScheme, SCHEME_LOCAL);
  979. }
  980. hr = piadp->QueryInterface(IID_PPV_ARG(IActiveDesktop, ppActiveDesktop));
  981. piadp->Release();
  982. }
  983. }
  984. else
  985. {
  986. (*ppActiveDesktop)->AddRef();
  987. }
  988. return hr;
  989. }
  990. HRESULT CThemePreview_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
  991. {
  992. HRESULT hr = E_INVALIDARG;
  993. if (punkOuter)
  994. {
  995. return CLASS_E_NOAGGREGATION;
  996. }
  997. if (ppvObj)
  998. {
  999. CPreviewTheme * pObject = new CPreviewTheme();
  1000. *ppvObj = NULL;
  1001. if (pObject)
  1002. {
  1003. hr = pObject->_Init();
  1004. if (SUCCEEDED(hr))
  1005. {
  1006. hr = pObject->QueryInterface(riid, ppvObj);
  1007. }
  1008. pObject->Release();
  1009. }
  1010. else
  1011. {
  1012. hr = E_OUTOFMEMORY;
  1013. }
  1014. }
  1015. return hr;
  1016. }