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.

252 lines
7.4 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1992 - 1999
  5. *
  6. * File: caption.cpp
  7. *
  8. * Contents: Implementation file for caption helper functions
  9. *
  10. * History: 19-Aug-98 jeffro Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #include "stdafx.h"
  14. #include "caption.h"
  15. #include "fontlink.h"
  16. #include "util.h"
  17. static void ComputeCaptionRects (CFrameWnd* pwnd, CRect& rectFullCaption,
  18. CRect& rectCaptionText, NONCLIENTMETRICS* pncm);
  19. static bool GradientFillRect (HDC hdc, LPCRECT pRect, bool fActive);
  20. static bool GradientFillRect (HDC hdc, LPCRECT pRect,
  21. COLORREF clrGradientLeft,
  22. COLORREF clrGradientRight);
  23. /*+-------------------------------------------------------------------------*
  24. * DrawFrameCaption
  25. *
  26. *
  27. *--------------------------------------------------------------------------*/
  28. bool DrawFrameCaption (CFrameWnd* pwndFrame, bool fActive)
  29. {
  30. /*
  31. * whistler always does the right thing, so short out if we're running there
  32. */
  33. if (IsWhistler())
  34. return (false);
  35. CWindowDC dc(pwndFrame);
  36. NONCLIENTMETRICS ncm;
  37. ncm.cbSize = sizeof (ncm);
  38. SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
  39. /*
  40. * create the caption font and select it into the DC
  41. */
  42. CFont font;
  43. font.CreateFontIndirect (&ncm.lfCaptionFont);
  44. CFont* pOldFont = dc.SelectObject (&font);
  45. /*
  46. * get the text to draw
  47. */
  48. CString strCaption;
  49. pwndFrame->GetWindowText (strCaption);
  50. /*
  51. * create CFontLinker and CRichText objects to determine if we
  52. * need to draw the text ourselves
  53. */
  54. USES_CONVERSION;
  55. CRichText rt (dc, T2CW (strCaption));
  56. CFontLinker fl;
  57. if (!fl.ComposeRichText(rt) || rt.IsDefaultFontSufficient())
  58. {
  59. dc.SelectObject (pOldFont);
  60. return (false);
  61. }
  62. /*-------------------------------------------------------*/
  63. /* if we get here, the default drawing isn't sufficient; */
  64. /* draw the caption ourselves */
  65. /*-------------------------------------------------------*/
  66. /*
  67. * get the bounding rects for the full caption and the text portion
  68. */
  69. CRect rectFullCaption;
  70. CRect rectCaptionText;
  71. ComputeCaptionRects (pwndFrame, rectFullCaption, rectCaptionText, &ncm);
  72. /*
  73. * clip output to the caption text rect, to minimize destruction
  74. * in the event that something dire happens
  75. */
  76. dc.IntersectClipRect (rectCaptionText);
  77. /*
  78. * gradient-fill the full caption rect (not just the title rect)
  79. * so the gradient will overlay seamlessly
  80. */
  81. if (!GradientFillRect (dc, rectFullCaption, fActive))
  82. {
  83. const int nBackColorIndex = (fActive) ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION;
  84. dc.FillSolidRect (rectCaptionText, GetSysColor (nBackColorIndex));
  85. }
  86. /*
  87. * set up text colors and background mix mode
  88. */
  89. const int nTextColorIndex = (fActive) ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT;
  90. COLORREF clrText = dc.SetTextColor (GetSysColor (nTextColorIndex));
  91. int nBkMode = dc.SetBkMode (TRANSPARENT);
  92. /*
  93. * draw the text
  94. */
  95. rt.Draw (rectCaptionText, fl.GetDrawTextFlags ());
  96. /*
  97. * restore the DC
  98. */
  99. dc.SetTextColor (clrText);
  100. dc.SetBkMode (nBkMode);
  101. dc.SelectObject (pOldFont);
  102. return (true);
  103. }
  104. /*+-------------------------------------------------------------------------*
  105. * ComputeCaptionRects
  106. *
  107. *
  108. *--------------------------------------------------------------------------*/
  109. static void ComputeCaptionRects (
  110. CFrameWnd* pwnd,
  111. CRect& rectFullCaption,
  112. CRect& rectCaptionText,
  113. NONCLIENTMETRICS* pncm)
  114. {
  115. /*
  116. * start with the full window rect, normalized around (0,0)
  117. */
  118. pwnd->GetWindowRect (rectFullCaption);
  119. rectFullCaption.OffsetRect (-rectFullCaption.left, -rectFullCaption.top);
  120. /*
  121. * assume sizing border
  122. */
  123. rectFullCaption.InflateRect (-GetSystemMetrics (SM_CXSIZEFRAME),
  124. -GetSystemMetrics (SM_CYSIZEFRAME));
  125. /*
  126. * correct the height
  127. */
  128. rectFullCaption.bottom = rectFullCaption.top + pncm->iCaptionHeight;
  129. /*
  130. * assume a system menu
  131. */
  132. rectCaptionText = rectFullCaption;
  133. rectCaptionText.left += pncm->iCaptionWidth + 2;
  134. /*
  135. * assume min, max, close buttons
  136. */
  137. rectCaptionText.right -= pncm->iCaptionWidth * 3;
  138. }
  139. /*+-------------------------------------------------------------------------*
  140. * GradientFillRect
  141. *
  142. *
  143. *--------------------------------------------------------------------------*/
  144. static bool GradientFillRect (HDC hdc, LPCRECT pRect, bool fActive)
  145. {
  146. #if (WINVER < 0x0500)
  147. #define COLOR_GRADIENTACTIVECAPTION 27
  148. #define COLOR_GRADIENTINACTIVECAPTION 28
  149. #endif
  150. int nLeftColor = (fActive) ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION;
  151. int nRightColor = (fActive) ? COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION;
  152. return (GradientFillRect (hdc, pRect,
  153. GetSysColor (nLeftColor),
  154. GetSysColor (nRightColor)));
  155. }
  156. /*+-------------------------------------------------------------------------*
  157. * GradientFillRect
  158. *
  159. *
  160. *--------------------------------------------------------------------------*/
  161. static bool GradientFillRect (HDC hdc, LPCRECT pRect, COLORREF clrGradientLeft, COLORREF clrGradientRight)
  162. {
  163. #if (WINVER < 0x0500)
  164. #define SPI_GETGRADIENTCAPTIONS 0x1008
  165. #endif
  166. typedef BOOL (WINAPI* GradientFillFuncPtr)( HDC hdc, CONST PTRIVERTEX pVertex, DWORD dwNumVertex,
  167. CONST PVOID pMesh, DWORD dwNumMesh, DWORD dwMode);
  168. // Query if gradient caption enabled, if query fails assume disabled
  169. BOOL bGradientEnabled;
  170. if (!SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bGradientEnabled, 0))
  171. bGradientEnabled = FALSE;
  172. if (!bGradientEnabled)
  173. return (false);
  174. static GradientFillFuncPtr pfnGradientFill = NULL;
  175. static bool fAttemptedGetProcAddress = false;
  176. // Locate GradientFill function
  177. if (!fAttemptedGetProcAddress)
  178. {
  179. fAttemptedGetProcAddress = true;
  180. HINSTANCE hInst = LoadLibrary(TEXT("msimg32.dll"));
  181. if (hInst)
  182. pfnGradientFill = (GradientFillFuncPtr)GetProcAddress(hInst, "GradientFill");
  183. }
  184. if (pfnGradientFill == NULL)
  185. return (false);
  186. // Do gradient fill
  187. TRIVERTEX vert[2] ;
  188. vert [0].x = pRect->left;
  189. vert [0].y = pRect->top;
  190. vert [0].Red = (clrGradientLeft << 8) & 0xff00;
  191. vert [0].Green = (clrGradientLeft) & 0xff00;
  192. vert [0].Blue = (clrGradientLeft >> 8) & 0xff00;
  193. vert [0].Alpha = 0x0000;
  194. vert [1].x = pRect->right;
  195. vert [1].y = pRect->bottom;
  196. vert [1].Red = (clrGradientRight << 8) & 0xff00;
  197. vert [1].Green = (clrGradientRight) & 0xff00;
  198. vert [1].Blue = (clrGradientRight >> 8) & 0xff00;
  199. vert [1].Alpha = 0x0000;
  200. GRADIENT_RECT gRect[1];
  201. gRect[0].UpperLeft = 0;
  202. gRect[0].LowerRight = 1;
  203. (*pfnGradientFill) (hdc, vert, countof (vert),
  204. gRect, countof (gRect), GRADIENT_FILL_RECT_H);
  205. return (true);
  206. }