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.

925 lines
28 KiB

  1. /*****************************************************************************\
  2. FILE: PreviewSM.cpp
  3. DESCRIPTION:
  4. This code will display a preview of system metrics.
  5. NOTE: This code will >hand< draw all the window controls, so if
  6. windows changes the way the windows controls are draw, this code
  7. needs to be manually updated. This is an issue for skinning.
  8. ??????? ?/??/1993 Created
  9. BryanSt 3/23/2000 Updated and Converted to C++
  10. Copyright (C) Microsoft Corp 1993-2000. All rights reserved.
  11. \*****************************************************************************/
  12. #include "priv.h"
  13. #include "PreviewSM.h"
  14. #include "AdvAppearPg.h"
  15. #define RCZ(element) g_elements[element].rc
  16. TCHAR g_szActive[CCH_MAX_STRING];
  17. TCHAR g_szInactive[CCH_MAX_STRING];
  18. TCHAR g_szMinimized[CCH_MAX_STRING];
  19. TCHAR g_szIconTitle[CCH_MAX_STRING];
  20. TCHAR g_szNormal[CCH_MAX_STRING];
  21. TCHAR g_szDisabled[CCH_MAX_STRING];
  22. TCHAR g_szSelected[CCH_MAX_STRING];
  23. TCHAR g_szMsgBox[CCH_MAX_STRING];
  24. TCHAR g_szButton[CCH_MAX_STRING];
  25. //TCHAR g_szSmallCaption[40];
  26. TCHAR g_szWindowText[CCH_MAX_STRING];
  27. TCHAR g_szMsgBoxText[CCH_MAX_STRING];
  28. TCHAR g_szABC[] = TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
  29. int cxSize;
  30. HMENU g_hmenuSample;
  31. HBITMAP g_hbmLook = NULL; // bitmap for the appearance preview
  32. int g_nBitsPixel = 0; // bits pizel for the appearance preview
  33. HDC g_hdcMem;
  34. HBITMAP g_hbmDefault;
  35. BOOL g_bMirroredOS = FALSE;
  36. int cyBorder;
  37. int cxBorder;
  38. int cyEdge;
  39. int cxEdge;
  40. //===========================
  41. // *** Class Internals & Helpers ***
  42. //===========================
  43. // Note that the rectangles are defined back to front. So we walk through
  44. // the list backwards, checking PtInRect() until we find a match.
  45. int LookPrev_HitTest(POINT pt)
  46. {
  47. int i;
  48. // start with last, don't bother with 0 (desktop)... it's the fallback
  49. for (i = NUM_ELEMENTS - 1; i > 0; i--)
  50. {
  51. if (PtInRect(&RCZ(i), pt))
  52. {
  53. break;
  54. }
  55. }
  56. // if the chosen one is really a dupe of another, use the base one
  57. if (g_elements[i].iBaseElement != -1)
  58. {
  59. i = g_elements[i].iBaseElement;
  60. }
  61. return i;
  62. }
  63. HRESULT CAdvAppearancePage::_OnNCCreate(HWND hWnd)
  64. {
  65. DWORD dwWindowStyles = GetWindowLong(hWnd, GWL_STYLE);
  66. SetWindowLong(hWnd, GWL_STYLE, dwWindowStyles | WS_BORDER);
  67. dwWindowStyles = GetWindowLong(hWnd,GWL_EXSTYLE);
  68. SetWindowLong(hWnd, GWL_EXSTYLE, dwWindowStyles | WS_EX_CLIENTEDGE);
  69. return S_OK;
  70. }
  71. HRESULT CAdvAppearancePage::_OnCreatePreviewSMDlg(LPRECT prc, BOOL fRTL)
  72. {
  73. cyBorder = ClassicGetSystemMetrics(SM_CYBORDER);
  74. cxBorder = ClassicGetSystemMetrics(SM_CXBORDER);
  75. cyEdge = ClassicGetSystemMetrics(SM_CXEDGE);
  76. cxEdge = ClassicGetSystemMetrics(SM_CYEDGE);
  77. _InitPreview(prc, fRTL);
  78. return S_OK;
  79. }
  80. // ----------------------------------------------------------------------------
  81. // create the preview bitmap and collect all of the global, non-changing data
  82. // ----------------------------------------------------------------------------
  83. void CAdvAppearancePage::_InitPreview(LPRECT prc, BOOL fRTL)
  84. {
  85. RECT rc;
  86. HDC hdc;
  87. rc = *prc;
  88. hdc = GetDC(NULL);
  89. g_nBitsPixel = GetDeviceCaps(hdc, BITSPIXEL);
  90. g_hbmLook = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);
  91. ReleaseDC(NULL, hdc);
  92. // Load our display strings.
  93. LoadString(HINST_THISDLL, IDS_ACTIVE, g_szActive, ARRAYSIZE(g_szActive));
  94. LoadString(HINST_THISDLL, IDS_INACTIVE, g_szInactive, ARRAYSIZE(g_szInactive));
  95. LoadString(HINST_THISDLL, IDS_MINIMIZED, g_szMinimized, ARRAYSIZE(g_szMinimized));
  96. LoadString(HINST_THISDLL, IDS_ICONTITLE, g_szIconTitle, ARRAYSIZE(g_szIconTitle));
  97. LoadString(HINST_THISDLL, IDS_NORMAL, g_szNormal, ARRAYSIZE(g_szNormal));
  98. LoadString(HINST_THISDLL, IDS_DISABLED, g_szDisabled, ARRAYSIZE(g_szDisabled));
  99. LoadString(HINST_THISDLL, IDS_SELECTED, g_szSelected, ARRAYSIZE(g_szSelected));
  100. LoadString(HINST_THISDLL, IDS_MSGBOX, g_szMsgBox, ARRAYSIZE(g_szMsgBox));
  101. LoadString(HINST_THISDLL, IDS_BUTTONTEXT, g_szButton, ARRAYSIZE(g_szButton));
  102. // LoadString(HINST_THISDLL, IDS_SMCAPTION, g_szSmallCaption, ARRAYSIZE(g_szSmallCaption));
  103. LoadString(HINST_THISDLL, IDS_WINDOWTEXT, g_szWindowText, ARRAYSIZE(g_szWindowText));
  104. LoadString(HINST_THISDLL, IDS_MSGBOXTEXT, g_szMsgBoxText, ARRAYSIZE(g_szMsgBoxText));
  105. // load up and
  106. g_hmenuSample = LoadMenu(HINST_THISDLL, MAKEINTRESOURCE(IDR_MENU));
  107. EnableMenuItem(g_hmenuSample, IDM_DISABLED, MF_GRAYED | MF_BYCOMMAND);
  108. // can do this here because hwnd is not yet visible
  109. // HiliteMenuItem(GetDesktopWindow(), g_hmenuSample, IDM_SELECTED, MF_HILITE | MF_BYCOMMAND);
  110. if (fRTL) {
  111. SET_DC_RTL_MIRRORED(g_hdcMem);
  112. }
  113. }
  114. HRESULT CAdvAppearancePage::_OnDestroyPreview(HWND hWnd)
  115. {
  116. if (g_hbmLook)
  117. {
  118. DeleteObject(g_hbmLook);
  119. g_hbmLook = NULL;
  120. }
  121. if (g_hmenuSample)
  122. {
  123. DestroyMenu(g_hmenuSample);
  124. g_hmenuSample = NULL;
  125. }
  126. return S_OK;
  127. }
  128. HRESULT CAdvAppearancePage::_OnPaintPreview(HWND hWnd)
  129. {
  130. PAINTSTRUCT ps;
  131. BeginPaint(hWnd, &ps);
  132. RECT rc;
  133. GetClientRect(hWnd, &rc);
  134. if (g_hbmLook)
  135. _ShowBitmap(hWnd, ps.hdc);
  136. else
  137. _DrawPreview(ps.hdc, &rc, FALSE, TRUE);
  138. EndPaint(hWnd, &ps);
  139. return S_OK;
  140. }
  141. HRESULT CAdvAppearancePage::_OnReCreateBitmap(HWND hWnd)
  142. {
  143. if (g_hbmLook)
  144. {
  145. HDC hdc = GetDC(NULL);
  146. if (g_nBitsPixel != GetDeviceCaps(hdc, BITSPIXEL))
  147. {
  148. DeleteObject(g_hbmLook);
  149. g_hbmLook = NULL;
  150. RECT rc;
  151. GetClientRect(hWnd, &rc);
  152. _InitPreview(&rc, IS_WINDOW_RTL_MIRRORED(hWnd));
  153. // InvalidateRect(hWnd, NULL, FALSE);
  154. // UpdateWindow(hWnd);
  155. _RepaintPreview(hWnd);
  156. }
  157. ReleaseDC(NULL, hdc);
  158. }
  159. return S_OK;
  160. }
  161. HRESULT CAdvAppearancePage::_OnButtonDownOrDblClick(HWND hWnd, int nCoordX, int nCoordY)
  162. {
  163. POINT pt;
  164. pt.x = nCoordX; // horizontal position of cursor
  165. pt.y = nCoordY; // vertical position of cursor
  166. int nElementIndex = LookPrev_HitTest(pt);
  167. return _SelectElement(hWnd, nElementIndex, LSE_SETCUR);
  168. }
  169. LRESULT CALLBACK CAdvAppearancePage::PreviewSystemMetricsWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  170. {
  171. CAdvAppearancePage * pThis = (CAdvAppearancePage *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  172. if (!pThis && (WM_NCDESTROY != wMsg))
  173. {
  174. AssertMsg((NULL != g_pAdvAppearancePage), TEXT("We need this or the dlg doesn't work at all. -BryanSt"));
  175. if (g_pAdvAppearancePage)
  176. {
  177. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)g_pAdvAppearancePage);
  178. pThis = (CAdvAppearancePage *)g_pAdvAppearancePage;
  179. }
  180. }
  181. if (pThis)
  182. return pThis->_PreviewSystemMetricsWndProc(hWnd, wMsg, wParam, lParam);
  183. return DefWindowProc(hWnd, wMsg, wParam, lParam);
  184. }
  185. // This Property Sheet appear in the top level of the "Display Control Panel".
  186. LRESULT CAdvAppearancePage::_PreviewSystemMetricsWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  187. {
  188. LRESULT lReturnValue = TRUE;
  189. BOOL fCallWndProc = TRUE;
  190. switch(wMsg)
  191. {
  192. case WM_NCCREATE:
  193. _OnNCCreate(hWnd);
  194. fCallWndProc = FALSE;
  195. break;
  196. case WM_CREATE:
  197. {
  198. RECT rc;
  199. GetClientRect(hWnd, &rc);
  200. _OnCreatePreviewSMDlg(&rc, IS_WINDOW_RTL_MIRRORED(hWnd));
  201. }
  202. break;
  203. case WM_DESTROY:
  204. _OnDestroyPreview(hWnd);
  205. break;
  206. case WM_PALETTECHANGED:
  207. if ((HWND)wParam == hWnd)
  208. break;
  209. //fallthru
  210. case WM_QUERYNEWPALETTE:
  211. if (m_hpal3D)
  212. InvalidateRect(hWnd, NULL, FALSE);
  213. break;
  214. case WM_LBUTTONDOWN:
  215. case WM_LBUTTONDBLCLK:
  216. _OnButtonDownOrDblClick(GetParent(hWnd), LOWORD(lParam), HIWORD(lParam));
  217. break;
  218. case WM_RECREATEBITMAP:
  219. _OnReCreateBitmap(hWnd);
  220. break;
  221. case WM_SIZE: // right mouse click
  222. break;
  223. case WM_PAINT:
  224. _OnPaintPreview(hWnd);
  225. break;
  226. }
  227. if (fCallWndProc)
  228. {
  229. lReturnValue = DefWindowProc(hWnd, wMsg, wParam, lParam);
  230. }
  231. return lReturnValue;
  232. }
  233. // ----------------------------------------------------------------------------
  234. // calculate all of the rectangles based on the given window rect
  235. // ----------------------------------------------------------------------------
  236. void CAdvAppearancePage::_Recalc(LPRECT prc)
  237. {
  238. DWORD cxNormal;
  239. int cxDisabled, cxSelected;
  240. int cxAvgCharx2;
  241. RECT rc;
  242. HFONT hfontT;
  243. int cxFrame, cyFrame;
  244. int cyCaption;
  245. int i;
  246. SIZE sizButton;
  247. rc = *prc;
  248. // Get our drawing data
  249. cxSize = ClassicGetSystemMetrics(SM_CXSIZE);
  250. cxFrame = (m_sizes[SIZE_FRAME].CurSize + 1) * m_cxBorderSM + m_cxEdgeSM;
  251. cyFrame = (m_sizes[SIZE_FRAME].CurSize + 1) * m_cyBorderSM + m_cyEdgeSM;
  252. cyCaption = m_sizes[SIZE_CAPTION].CurSize;
  253. // Get text dimensions, with proper font.
  254. hfontT = (HFONT) SelectObject(g_hdcMem, m_fonts[FONT_MENU].hfont);
  255. GetTextExtentPoint32(g_hdcMem, g_szNormal, lstrlen(g_szNormal), &sizButton);
  256. cxNormal = sizButton.cx;
  257. GetTextExtentPoint32(g_hdcMem, g_szDisabled, lstrlen(g_szDisabled), &sizButton);
  258. cxDisabled = sizButton.cx;
  259. GetTextExtentPoint32(g_hdcMem, g_szSelected, lstrlen(g_szSelected), &sizButton);
  260. cxSelected = sizButton.cx;
  261. // get the average width (USER style) of menu font
  262. GetTextExtentPoint32(g_hdcMem, g_szABC, 52, &sizButton);
  263. cxAvgCharx2 = 2 * (sizButton.cx / 52);
  264. // actual menu-handling widths of strings is bigger
  265. cxDisabled += cxAvgCharx2;
  266. cxSelected += cxAvgCharx2;
  267. cxNormal += cxAvgCharx2;
  268. SelectObject(g_hdcMem, hfontT);
  269. GetTextExtentPoint32(g_hdcMem, g_szButton, lstrlen(g_szButton), &sizButton);
  270. // Desktop
  271. RCZ(ELEMENT_DESKTOP) = rc;
  272. InflateRect(&rc, -8*m_cxBorderSM, -8*m_cyBorderSM);
  273. // Windows
  274. rc.bottom -= cyFrame + cyCaption;
  275. RCZ(ELEMENT_ACTIVEBORDER) = rc;
  276. OffsetRect(&RCZ(ELEMENT_ACTIVEBORDER), cxFrame,
  277. cyFrame + cyCaption + m_cyBorderSM);
  278. RCZ(ELEMENT_ACTIVEBORDER).bottom -= cyCaption;
  279. // Inactive window
  280. rc.right -= cyCaption;
  281. RCZ(ELEMENT_INACTIVEBORDER) = rc;
  282. // Caption
  283. InflateRect(&rc, -cxFrame, -cyFrame);
  284. rc.bottom = rc.top + cyCaption + m_cyBorderSM;
  285. RCZ(ELEMENT_INACTIVECAPTION) = rc;
  286. // close button
  287. InflateRect(&rc, -m_cxEdgeSM, -m_cyEdgeSM);
  288. rc.bottom -= m_cyBorderSM; // compensate for magic line under caption
  289. RCZ(ELEMENT_INACTIVESYSBUT1) = rc;
  290. RCZ(ELEMENT_INACTIVESYSBUT1).left = rc.right - (cyCaption - m_cxEdgeSM);
  291. // min/max buttons
  292. RCZ(ELEMENT_INACTIVESYSBUT2) = rc;
  293. RCZ(ELEMENT_INACTIVESYSBUT2).right = RCZ(ELEMENT_INACTIVESYSBUT1).left - m_cxEdgeSM;
  294. RCZ(ELEMENT_INACTIVESYSBUT2).left = RCZ(ELEMENT_INACTIVESYSBUT2).right -
  295. 2 * (cyCaption - m_cxEdgeSM);
  296. #if 0
  297. // small caption window
  298. RCZ(ELEMENT_SMCAPTION) = RCZ(ELEMENT_ACTIVEBORDER);
  299. RCZ(ELEMENT_SMCAPTION).bottom = RCZ(ELEMENT_SMCAPTION).top;
  300. RCZ(ELEMENT_SMCAPTION).top -= m_sizes[SIZE_SMCAPTION].CurSize + m_cyEdgeSM + 2 * m_cyBorderSM;
  301. RCZ(ELEMENT_SMCAPTION).right -= cxFrame;
  302. RCZ(ELEMENT_SMCAPTION).left = RCZ(ELEMENT_INACTIVECAPTION).right + 2 * cxFrame;
  303. RCZ(ELEMENT_SMCAPSYSBUT) = RCZ(ELEMENT_SMCAPTION);
  304. // deflate inside frame/border to caption and then another edge's worth
  305. RCZ(ELEMENT_SMCAPSYSBUT).right -= 2 * m_cxEdgeSM + m_cxBorderSM;
  306. RCZ(ELEMENT_SMCAPSYSBUT).top += 2 * m_cxEdgeSM + m_cxBorderSM;
  307. RCZ(ELEMENT_SMCAPSYSBUT).bottom -= m_cxEdgeSM + m_cxBorderSM;
  308. RCZ(ELEMENT_SMCAPSYSBUT).left = RCZ(ELEMENT_SMCAPSYSBUT).right -
  309. (m_sizes[SIZE_SMCAPTION].CurSize - m_cxEdgeSM);
  310. #endif
  311. // Active window
  312. // Caption
  313. rc = RCZ(ELEMENT_ACTIVEBORDER);
  314. InflateRect(&rc, -cxFrame, -cyFrame);
  315. RCZ(ELEMENT_ACTIVECAPTION) = rc;
  316. RCZ(ELEMENT_ACTIVECAPTION).bottom =
  317. RCZ(ELEMENT_ACTIVECAPTION).top + cyCaption + m_cyBorderSM;
  318. // close button
  319. RCZ(ELEMENT_ACTIVESYSBUT1) = RCZ(ELEMENT_ACTIVECAPTION);
  320. InflateRect(&RCZ(ELEMENT_ACTIVESYSBUT1), -m_cxEdgeSM, -m_cyEdgeSM);
  321. RCZ(ELEMENT_ACTIVESYSBUT1).bottom -= m_cyBorderSM; // compensate for magic line under caption
  322. RCZ(ELEMENT_ACTIVESYSBUT1).left = RCZ(ELEMENT_ACTIVESYSBUT1).right -
  323. (cyCaption - m_cxEdgeSM);
  324. // min/max buttons
  325. RCZ(ELEMENT_ACTIVESYSBUT2) = RCZ(ELEMENT_ACTIVESYSBUT1);
  326. RCZ(ELEMENT_ACTIVESYSBUT2).right = RCZ(ELEMENT_ACTIVESYSBUT1).left - m_cxEdgeSM;
  327. RCZ(ELEMENT_ACTIVESYSBUT2).left = RCZ(ELEMENT_ACTIVESYSBUT2).right -
  328. 2 * (cyCaption - m_cxEdgeSM);
  329. // Menu
  330. rc.top = RCZ(ELEMENT_ACTIVECAPTION).bottom;
  331. RCZ(ELEMENT_MENUNORMAL) = rc;
  332. rc.top = RCZ(ELEMENT_MENUNORMAL).bottom = RCZ(ELEMENT_MENUNORMAL).top + m_sizes[SIZE_MENU].CurSize;
  333. RCZ(ELEMENT_MENUDISABLED) = RCZ(ELEMENT_MENUSELECTED) = RCZ(ELEMENT_MENUNORMAL);
  334. RCZ(ELEMENT_MENUDISABLED).left = RCZ(ELEMENT_MENUNORMAL).left + cxNormal;
  335. RCZ(ELEMENT_MENUDISABLED).right = RCZ(ELEMENT_MENUSELECTED).left =
  336. RCZ(ELEMENT_MENUDISABLED).left + cxDisabled;
  337. RCZ(ELEMENT_MENUSELECTED).right = RCZ(ELEMENT_MENUSELECTED).left + cxSelected;
  338. // Client
  339. RCZ(ELEMENT_WINDOW) = rc;
  340. // Scrollbar
  341. InflateRect(&rc, -m_cxEdgeSM, -m_cyEdgeSM); // take off client edge
  342. RCZ(ELEMENT_SCROLLBAR) = rc;
  343. rc.right = RCZ(ELEMENT_SCROLLBAR).left = rc.right - m_sizes[SIZE_SCROLL].CurSize;
  344. RCZ(ELEMENT_SCROLLUP) = RCZ(ELEMENT_SCROLLBAR);
  345. RCZ(ELEMENT_SCROLLUP).bottom = RCZ(ELEMENT_SCROLLBAR).top + m_sizes[SIZE_SCROLL].CurSize;
  346. RCZ(ELEMENT_SCROLLDOWN) = RCZ(ELEMENT_SCROLLBAR);
  347. RCZ(ELEMENT_SCROLLDOWN).top = RCZ(ELEMENT_SCROLLBAR).bottom - m_sizes[SIZE_SCROLL].CurSize;
  348. // Message Box
  349. rc.top = RCZ(ELEMENT_WINDOW).top + (RCZ(ELEMENT_WINDOW).bottom - RCZ(ELEMENT_WINDOW).top) / 2;
  350. rc.bottom = RCZ(ELEMENT_DESKTOP).bottom - 2*m_cyEdgeSM;
  351. rc.left = RCZ(ELEMENT_WINDOW).left + 2*m_cyEdgeSM;
  352. rc.right = RCZ(ELEMENT_WINDOW).left + (RCZ(ELEMENT_WINDOW).right - RCZ(ELEMENT_WINDOW).left) / 2 + 3*cyCaption;
  353. RCZ(ELEMENT_MSGBOX) = rc;
  354. // Caption
  355. RCZ(ELEMENT_MSGBOXCAPTION) = rc;
  356. RCZ(ELEMENT_MSGBOXCAPTION).top += m_cyEdgeSM + m_cyBorderSM;
  357. RCZ(ELEMENT_MSGBOXCAPTION).bottom = RCZ(ELEMENT_MSGBOXCAPTION).top + cyCaption + m_cyBorderSM;
  358. RCZ(ELEMENT_MSGBOXCAPTION).left += m_cxEdgeSM + m_cxBorderSM;
  359. RCZ(ELEMENT_MSGBOXCAPTION).right -= m_cxEdgeSM + m_cxBorderSM;
  360. RCZ(ELEMENT_MSGBOXSYSBUT) = RCZ(ELEMENT_MSGBOXCAPTION);
  361. InflateRect(&RCZ(ELEMENT_MSGBOXSYSBUT), -m_cxEdgeSM, -m_cyEdgeSM);
  362. RCZ(ELEMENT_MSGBOXSYSBUT).left = RCZ(ELEMENT_MSGBOXSYSBUT).right -
  363. (cyCaption - m_cxEdgeSM);
  364. RCZ(ELEMENT_MSGBOXSYSBUT).bottom -= m_cyBorderSM; // line under caption
  365. // Button
  366. RCZ(ELEMENT_BUTTON).bottom = RCZ(ELEMENT_MSGBOX).bottom - (4*m_cyBorderSM + m_cyEdgeSM);
  367. RCZ(ELEMENT_BUTTON).top = RCZ(ELEMENT_BUTTON).bottom - (sizButton.cy + 8 * m_cyBorderSM);
  368. i = (RCZ(ELEMENT_BUTTON).bottom - RCZ(ELEMENT_BUTTON).top) * 3;
  369. RCZ(ELEMENT_BUTTON).left = (rc.left + (rc.right - rc.left)/2) - i/2;
  370. RCZ(ELEMENT_BUTTON).right = RCZ(ELEMENT_BUTTON).left + i;
  371. }
  372. // ----------------------------------------------------------------------------
  373. //
  374. // MyDrawFrame() -
  375. //
  376. // Draws bordered frame, border size cl, and adjusts passed in rect.
  377. //
  378. // ----------------------------------------------------------------------------
  379. void MyDrawFrame(HDC hdc, LPRECT prc, HBRUSH hbrColor, int cl)
  380. {
  381. HBRUSH hbr;
  382. int cx, cy;
  383. RECT rcT;
  384. rcT = *prc;
  385. cx = cl * cxBorder;
  386. cy = cl * cyBorder;
  387. hbr = (HBRUSH) SelectObject(hdc, hbrColor);
  388. PatBlt(hdc, rcT.left, rcT.top, cx, rcT.bottom - rcT.top, PATCOPY);
  389. rcT.left += cx;
  390. PatBlt(hdc, rcT.left, rcT.top, rcT.right - rcT.left, cy, PATCOPY);
  391. rcT.top += cy;
  392. rcT.right -= cx;
  393. PatBlt(hdc, rcT.right, rcT.top, cx, rcT.bottom - rcT.top, PATCOPY);
  394. rcT.bottom -= cy;
  395. PatBlt(hdc, rcT.left, rcT.bottom, rcT.right - rcT.left, cy, PATCOPY);
  396. hbr = (HBRUSH) SelectObject(hdc, hbr);
  397. *prc = rcT;
  398. }
  399. /*
  400. ** draw a m_cyBorderSM band of 3DFACE at the bottom of the given rectangle.
  401. ** also, adjust the rectangle accordingly.
  402. */
  403. void CAdvAppearancePage::_MyDrawBorderBelow(HDC hdc, LPRECT prc)
  404. {
  405. int i;
  406. i = prc->top;
  407. prc->top = prc->bottom - m_cyBorderSM;
  408. FillRect(hdc, prc, m_brushes[COLOR_3DFACE]);
  409. prc->top = i;
  410. prc->bottom -= m_cyBorderSM;
  411. }
  412. /*-------------------------------------------------------------------
  413. ** draw a full window caption with system menu, minimize button,
  414. ** maximize button, and text.
  415. **-------------------------------------------------------------------*/
  416. void CAdvAppearancePage::DrawFullCaption(HDC hdc, LPRECT prc, LPTSTR lpszTitle, UINT flags)
  417. {
  418. int iRight;
  419. int iFont;
  420. SaveDC(hdc);
  421. // special case gross for small caption that already drew on bottom
  422. if (!(flags & DC_SMALLCAP))
  423. _MyDrawBorderBelow(hdc, prc);
  424. iRight = prc->right;
  425. prc->right = prc->left + cxSize;
  426. DrawFrameControl(hdc, prc, DFC_CAPTION, DFCS_CAPTIONCLOSE);
  427. prc->left = prc->right;
  428. prc->right = iRight - 2*cxSize;
  429. iFont = flags & DC_SMALLCAP ? FONT_SMCAPTION : FONT_CAPTION;
  430. DrawCaptionTemp(NULL, hdc, prc, m_fonts[iFont].hfont, NULL, lpszTitle, flags | DC_ICON | DC_TEXT);
  431. prc->left = prc->right;
  432. prc->right = prc->left + cxSize;
  433. DrawFrameControl(hdc, prc, DFC_CAPTION, DFCS_CAPTIONMIN);
  434. prc->left = prc->right;
  435. prc->right = prc->left + cxSize;
  436. DrawFrameControl(hdc, prc, DFC_CAPTION, DFCS_CAPTIONMAX);
  437. RestoreDC(hdc, -1);
  438. }
  439. void CAdvAppearancePage::_ShowBitmap(HWND hWnd, HDC hdc)
  440. {
  441. RECT rc;
  442. HBITMAP hbmOld;
  443. HPALETTE hpalOld = NULL;
  444. if (m_hpal3D)
  445. {
  446. hpalOld = SelectPalette(hdc, m_hpal3D, FALSE);
  447. RealizePalette(hdc);
  448. }
  449. GetClientRect(hWnd, &rc);
  450. hbmOld = (HBITMAP) SelectObject(g_hdcMem, g_hbmLook);
  451. BitBlt(hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top, g_hdcMem, 0, 0, SRCCOPY);
  452. SelectObject(g_hdcMem, hbmOld);
  453. if (hpalOld)
  454. {
  455. SelectPalette(hdc, hpalOld, FALSE);
  456. RealizePalette(hdc);
  457. }
  458. }
  459. // ----------------------------------------------------------------------------
  460. //
  461. //
  462. // ----------------------------------------------------------------------------
  463. void CAdvAppearancePage::_DrawPreview(HDC hdc, LPRECT prc, BOOL fOnlyShowActiveWindow, BOOL fShowBack)
  464. {
  465. RECT rcT;
  466. int nMode;
  467. DWORD rgbBk;
  468. int cxSize, cySize;
  469. HANDLE hOldColors;
  470. HPALETTE hpalOld = NULL;
  471. HICON hiconLogo;
  472. HFONT hfontOld;
  473. BOOL bGradient = FALSE;
  474. ClassicSystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, (PVOID)&bGradient, 0);
  475. SaveDC(hdc);
  476. if (m_hpal3D)
  477. {
  478. hpalOld = SelectPalette(hdc, m_hpal3D, TRUE);
  479. RealizePalette(hdc);
  480. }
  481. hOldColors = SetSysColorsTemp(m_rgb, m_brushes, COLOR_MAX);
  482. hiconLogo = (HICON) LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON,
  483. m_sizes[SIZE_CAPTION].CurSize - 2*m_cxBorderSM,
  484. m_sizes[SIZE_CAPTION].CurSize - 2*m_cyBorderSM, 0);
  485. // Setup drawing stuff
  486. nMode = SetBkMode(hdc, TRANSPARENT);
  487. rgbBk = GetTextColor(hdc);
  488. cxSize = ClassicGetSystemMetrics(SM_CXSIZE);
  489. cySize = ClassicGetSystemMetrics(SM_CYSIZE);
  490. // Desktop
  491. if (fShowBack)
  492. {
  493. FillRect(hdc, &RCZ(ELEMENT_DESKTOP), m_brushes[COLOR_BACKGROUND]);
  494. }
  495. if (!fOnlyShowActiveWindow)
  496. {
  497. // Inactive window
  498. // Border
  499. rcT = RCZ(ELEMENT_INACTIVEBORDER);
  500. DrawEdge(hdc, &rcT, EDGE_RAISED, BF_RECT | BF_ADJUST);
  501. MyDrawFrame(hdc, &rcT, m_brushes[COLOR_INACTIVEBORDER], m_sizes[SIZE_FRAME].CurSize);
  502. MyDrawFrame(hdc, &rcT, m_brushes[COLOR_3DFACE], 1);
  503. // Caption
  504. rcT = RCZ(ELEMENT_INACTIVECAPTION);
  505. _MyDrawBorderBelow(hdc, &rcT);
  506. // NOTE: because USER draws icon stuff using its own DC and subsequently
  507. // its own palette, we need to make sure to use the inactivecaption
  508. // brush before USER does so that it will be realized against our palette.
  509. // this might get fixed in USER by better be safe.
  510. // "clip" the caption title under the buttons
  511. rcT.left = RCZ(ELEMENT_INACTIVESYSBUT2).left - m_cyEdgeSM;
  512. FillRect(hdc, &rcT, m_brushes[bGradient ? COLOR_GRADIENTINACTIVECAPTION : COLOR_INACTIVECAPTION]);
  513. rcT.right = rcT.left;
  514. rcT.left = RCZ(ELEMENT_INACTIVECAPTION).left;
  515. DrawCaptionTemp(NULL, hdc, &rcT, m_fonts[FONT_CAPTION].hfont, hiconLogo, g_szInactive, DC_ICON | DC_TEXT |
  516. (bGradient ? DC_GRADIENT : 0));
  517. DrawFrameControl(hdc, &RCZ(ELEMENT_INACTIVESYSBUT1), DFC_CAPTION, DFCS_CAPTIONCLOSE);
  518. rcT = RCZ(ELEMENT_INACTIVESYSBUT2);
  519. rcT.right -= (rcT.right - rcT.left)/2;
  520. DrawFrameControl(hdc, &rcT, DFC_CAPTION, DFCS_CAPTIONMIN);
  521. rcT.left = rcT.right;
  522. rcT.right = RCZ(ELEMENT_INACTIVESYSBUT2).right;
  523. DrawFrameControl(hdc, &rcT, DFC_CAPTION, DFCS_CAPTIONMAX);
  524. }
  525. // Active window
  526. // Border
  527. rcT = RCZ(ELEMENT_ACTIVEBORDER);
  528. DrawEdge(hdc, &rcT, EDGE_RAISED, BF_RECT | BF_ADJUST);
  529. MyDrawFrame(hdc, &rcT, m_brushes[COLOR_ACTIVEBORDER], m_sizes[SIZE_FRAME].CurSize);
  530. MyDrawFrame(hdc, &rcT, m_brushes[COLOR_3DFACE], 1);
  531. // Caption
  532. rcT = RCZ(ELEMENT_ACTIVECAPTION);
  533. _MyDrawBorderBelow(hdc, &rcT);
  534. // "clip" the caption title under the buttons
  535. rcT.left = RCZ(ELEMENT_ACTIVESYSBUT2).left - m_cxEdgeSM;
  536. FillRect(hdc, &rcT, m_brushes[bGradient ? COLOR_GRADIENTACTIVECAPTION : COLOR_ACTIVECAPTION]);
  537. rcT.right = rcT.left;
  538. rcT.left = RCZ(ELEMENT_ACTIVECAPTION).left;
  539. DrawCaptionTemp(NULL, hdc, &rcT, m_fonts[FONT_CAPTION].hfont, hiconLogo, g_szActive, DC_ACTIVE | DC_ICON | DC_TEXT |
  540. (bGradient ? DC_GRADIENT : 0));
  541. DrawFrameControl(hdc, &RCZ(ELEMENT_ACTIVESYSBUT1), DFC_CAPTION, DFCS_CAPTIONCLOSE);
  542. rcT = RCZ(ELEMENT_ACTIVESYSBUT2);
  543. rcT.right -= (rcT.right - rcT.left)/2;
  544. DrawFrameControl(hdc, &rcT, DFC_CAPTION, DFCS_CAPTIONMIN);
  545. rcT.left = rcT.right;
  546. rcT.right = RCZ(ELEMENT_ACTIVESYSBUT2).right;
  547. DrawFrameControl(hdc, &rcT, DFC_CAPTION, DFCS_CAPTIONMAX);
  548. // Menu
  549. rcT = RCZ(ELEMENT_MENUNORMAL);
  550. DrawMenuBarTemp(GetDesktopWindow(), hdc, &rcT, g_hmenuSample, m_fonts[FONT_MENU].hfont);
  551. _MyDrawBorderBelow(hdc, &rcT);
  552. // Client area
  553. rcT = RCZ(ELEMENT_WINDOW);
  554. DrawEdge(hdc, &rcT, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
  555. FillRect(hdc, &rcT, m_brushes[COLOR_WINDOW]);
  556. // window text
  557. SetBkMode(hdc, TRANSPARENT);
  558. SetTextColor(hdc, m_rgb[COLOR_WINDOWTEXT]);
  559. hfontOld = (HFONT) SelectObject(hdc, m_fonts[FONT_CAPTION].hfont);
  560. TextOut(hdc, RCZ(ELEMENT_WINDOW).left + 2*m_cxEdgeSM, RCZ(ELEMENT_WINDOW).top + 2*m_cyEdgeSM, g_szWindowText, lstrlen(g_szWindowText));
  561. if (hfontOld)
  562. SelectObject(hdc, hfontOld);
  563. // scroll bar
  564. rcT = RCZ(ELEMENT_SCROLLBAR);
  565. //MyDrawFrame(hdc, &rcT, m_brushes[COLOR_3DSHADOW], 1);
  566. //m_brushes[COLOR_SCROLLBAR]);
  567. FillRect(hdc, &rcT, m_brushes[COLOR_SCROLLBAR]);
  568. // FillRect(hdc, &rcT, (HBRUSH)DefWindowProc(hWnd, WM_CTLCOLOR, (WPARAM)hdc, MAKELONG(hWnd, CTLCOLOR_SCROLLBAR)));
  569. DrawFrameControl(hdc, &RCZ(ELEMENT_SCROLLUP), DFC_SCROLL, DFCS_SCROLLUP);
  570. DrawFrameControl(hdc, &RCZ(ELEMENT_SCROLLDOWN), DFC_SCROLL, DFCS_SCROLLDOWN);
  571. if (!fOnlyShowActiveWindow)
  572. {
  573. // MessageBox
  574. rcT = RCZ(ELEMENT_MSGBOX);
  575. DrawEdge(hdc, &rcT, EDGE_RAISED, BF_RECT | BF_ADJUST);
  576. FillRect(hdc, &rcT, m_brushes[COLOR_3DFACE]);
  577. rcT = RCZ(ELEMENT_MSGBOXCAPTION);
  578. _MyDrawBorderBelow(hdc, &rcT);
  579. // "clip" the caption title under the buttons
  580. rcT.left = RCZ(ELEMENT_MSGBOXSYSBUT).left - m_cxEdgeSM;
  581. FillRect(hdc, &rcT, m_brushes[bGradient ? COLOR_GRADIENTACTIVECAPTION : COLOR_ACTIVECAPTION]);
  582. rcT.right = rcT.left;
  583. rcT.left = RCZ(ELEMENT_MSGBOXCAPTION).left;
  584. DrawCaptionTemp(NULL, hdc, &rcT, m_fonts[FONT_CAPTION].hfont, hiconLogo, g_szMsgBox, DC_ACTIVE | DC_ICON | DC_TEXT |
  585. (bGradient ? DC_GRADIENT : 0));
  586. DrawFrameControl(hdc, &RCZ(ELEMENT_MSGBOXSYSBUT), DFC_CAPTION, DFCS_CAPTIONCLOSE);
  587. // message box text
  588. SetBkMode(hdc, TRANSPARENT);
  589. SetTextColor(hdc, m_rgb[COLOR_WINDOWTEXT]);
  590. hfontOld = (HFONT) SelectObject(hdc, m_fonts[FONT_MSGBOX].hfont);
  591. TextOut(hdc, RCZ(ELEMENT_MSGBOX).left + 3*m_cxEdgeSM, RCZ(ELEMENT_MSGBOXCAPTION).bottom + m_cyEdgeSM,
  592. g_szMsgBoxText, lstrlen(g_szMsgBoxText));
  593. if (hfontOld)
  594. SelectObject(hdc, hfontOld);
  595. // Button
  596. rcT = RCZ(ELEMENT_BUTTON);
  597. DrawFrameControl(hdc, &rcT, DFC_BUTTON, DFCS_BUTTONPUSH);
  598. // ?????? what font should this use ??????
  599. // [msadek]; Pick the same one we use for Messagebox text.(This is what Message Box uses for its buttons)
  600. // else we will be using the font originally selected in the DC (System font)
  601. hfontOld = (HFONT) SelectObject(hdc, m_fonts[FONT_MSGBOX].hfont);
  602. SetBkMode(hdc, TRANSPARENT);
  603. SetTextColor(hdc, m_rgb[COLOR_BTNTEXT]);
  604. DrawText(hdc, g_szButton, -1, &rcT, DT_CENTER | DT_NOPREFIX |
  605. DT_SINGLELINE | DT_VCENTER);
  606. if (hfontOld)
  607. SelectObject(hdc, hfontOld);
  608. }
  609. SetBkColor(hdc, rgbBk);
  610. SetBkMode(hdc, nMode);
  611. if (hiconLogo)
  612. DestroyIcon(hiconLogo);
  613. SetSysColorsTemp(NULL, NULL, (UINT_PTR)hOldColors);
  614. if (hpalOld)
  615. {
  616. hpalOld = SelectPalette(hdc, hpalOld, FALSE);
  617. RealizePalette(hdc);
  618. }
  619. RestoreDC(hdc, -1);
  620. }
  621. void CAdvAppearancePage::_RepaintPreview(HWND hwnd)
  622. {
  623. HBITMAP hbmOld;
  624. if (g_hbmLook)
  625. {
  626. hbmOld = (HBITMAP) SelectObject(g_hdcMem, g_hbmLook);
  627. RECT rc;
  628. GetClientRect(hwnd, &rc);
  629. _DrawPreview(g_hdcMem, &rc, FALSE, TRUE);
  630. SelectObject(g_hdcMem, hbmOld);
  631. }
  632. InvalidateRect(hwnd, NULL, FALSE);
  633. }
  634. BOOL RegisterPreviewSystemMetricClass(HINSTANCE hInst)
  635. {
  636. WNDCLASS wc;
  637. if (!GetClassInfo(hInst, PREVIEWSM_CLASS, &wc))
  638. {
  639. wc.style = 0;
  640. wc.lpfnWndProc = CAdvAppearancePage::PreviewSystemMetricsWndProc;
  641. wc.cbClsExtra = 0;
  642. wc.cbWndExtra = 0;
  643. wc.hInstance = hInst;
  644. wc.hIcon = NULL;
  645. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  646. wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
  647. wc.lpszMenuName = NULL;
  648. wc.lpszClassName = PREVIEWSM_CLASS;
  649. if (!RegisterClass(&wc))
  650. return FALSE;
  651. }
  652. return TRUE;
  653. }
  654. /*---------------------------------------------------------
  655. **
  656. **---------------------------------------------------------*/
  657. BOOL CreateGlobals(void)
  658. {
  659. HBITMAP hbm;
  660. HDC hdc;
  661. // Check if the mirroring APIs exist on the current
  662. // platform.
  663. g_bMirroredOS = IS_MIRRORING_ENABLED();
  664. if (!g_hdcMem)
  665. {
  666. hdc = GetDC(NULL);
  667. g_hdcMem = CreateCompatibleDC(hdc);
  668. ReleaseDC(NULL, hdc);
  669. }
  670. if (!g_hdcMem)
  671. return FALSE;
  672. if (!g_hbmDefault)
  673. {
  674. hbm = CreateBitmap(1, 1, 1, 1, NULL);
  675. if (hbm)
  676. {
  677. g_hbmDefault = (HBITMAP) SelectObject(g_hdcMem, hbm);
  678. SelectObject(g_hdcMem, g_hbmDefault);
  679. DeleteObject(hbm);
  680. }
  681. }
  682. return TRUE;
  683. }
  684. HRESULT CAdvAppearancePage::Draw(HDC hdc, LPRECT prc, BOOL fOnlyShowActiveWindow, BOOL fRTL)
  685. {
  686. _OnCreatePreviewSMDlg(prc, fRTL);
  687. m_cyBorderSM = ClassicGetSystemMetrics(SM_CYBORDER);
  688. m_cxBorderSM = ClassicGetSystemMetrics(SM_CXBORDER);
  689. m_cxEdgeSM = ClassicGetSystemMetrics(SM_CXEDGE);
  690. m_cyEdgeSM = ClassicGetSystemMetrics(SM_CYEDGE);
  691. _InitSysStuff();
  692. _Recalc(prc);
  693. _DrawPreview(hdc, prc, fOnlyShowActiveWindow, FALSE);
  694. _DestroySysStuff();
  695. if (g_hbmLook)
  696. {
  697. DeleteObject(g_hbmLook);
  698. }
  699. if (g_hmenuSample)
  700. {
  701. DestroyMenu(g_hmenuSample);
  702. }
  703. return S_OK;
  704. }
  705. HRESULT DrawAppearance(HDC hdc, LPRECT prc, SYSTEMMETRICSALL* psysMet, BOOL fOnlyShowActiveWindow, BOOL fRTL)
  706. {
  707. HRESULT hr = E_OUTOFMEMORY;
  708. CAdvAppearancePage* pAdv = new CAdvAppearancePage(psysMet);
  709. if (pAdv)
  710. {
  711. hr = pAdv->Draw(hdc, prc, fOnlyShowActiveWindow, fRTL);
  712. delete pAdv;
  713. }
  714. return hr;
  715. }