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.

342 lines
11 KiB

  1. /*************************************************************************/
  2. /* Copyright (C) 1999 Microsoft Corporation */
  3. /* File: ctext.cpp */
  4. /* Description: Implementation of ctext class for drawing text. */
  5. /* Author: phillu */
  6. /* Date: 10/06/99 */
  7. /*************************************************************************/
  8. #include "stdafx.h"
  9. #include "ctext.h"
  10. /*************************************************************************/
  11. /* Function: CText::CText() */
  12. /* Description: Initialize the properties and states. */
  13. /*************************************************************************/
  14. CText::CText()
  15. {
  16. m_fDirty = true;
  17. m_hFont = NULL;
  18. //properties
  19. m_uiFontSize = 10;
  20. m_uiAlignment = TA_CENTER;
  21. m_clrTextColor = GetSysColor(COLOR_WINDOWTEXT);
  22. m_bstrFontFace = L"Arial";
  23. m_bstrFontStyle = L"Normal";
  24. m_fFontStyleFlags = FS_NORMAL;
  25. m_fFixedSizeFont = false;
  26. }
  27. /*************************************************************************/
  28. /* Function: CText::~CText() */
  29. /* Description: Destroy the cached font. */
  30. /*************************************************************************/
  31. CText::~CText()
  32. {
  33. if (m_hFont)
  34. {
  35. ::DeleteObject(m_hFont);
  36. m_hFont = NULL;
  37. }
  38. }
  39. /*************************************************************************/
  40. /* Function: Write */
  41. /* Description: Draw text in the specified rectangle. */
  42. /* The font is not created until drawing text for the first time. */
  43. /* Assume the following settings: */
  44. /* - Use Transparent background mode; no change of bg color */
  45. /* - Vertical alignment is always centered */
  46. /*************************************************************************/
  47. HRESULT CText::Write(HDC hdc, const RECT & rc, const WCHAR * pwszText)
  48. {
  49. USES_CONVERSION;
  50. HRESULT hr = S_OK;
  51. const int cBorderMargin = 2; // 2 pixel margin on left or right border
  52. // set drawing attributes, save the old ones
  53. UINT uiOldAlign = ::SetTextAlign(hdc, m_uiAlignment|TA_BOTTOM);
  54. COLORREF crOldTextColor = ::SetTextColor(hdc, m_clrTextColor);
  55. int iOldBkMode = ::SetBkMode(hdc, TRANSPARENT);
  56. // create the required font
  57. if (m_fDirty)
  58. {
  59. hr = RealizeFont(hdc);
  60. }
  61. HFONT hOldFont = NULL;
  62. if (m_hFont)
  63. {
  64. hOldFont = (HFONT) ::SelectObject(hdc, m_hFont);
  65. }
  66. // set position of text based on alignment
  67. TEXTMETRIC tm;
  68. GetTextMetrics(hdc, &tm);
  69. int x = (rc.left + rc.right)/2;
  70. if (m_uiAlignment == TA_LEFT)
  71. {
  72. x = rc.left + cBorderMargin;
  73. }
  74. else if (m_uiAlignment == TA_RIGHT)
  75. {
  76. x = rc.right - cBorderMargin;
  77. }
  78. // text is aligned at the bottom. Adding half of text height makes
  79. // it to position at the center vertically
  80. int y = (rc.top + rc.bottom)/2 + tm.tmHeight/2;
  81. ::TextOut(hdc, x, y, W2CT(pwszText), wcslen(pwszText));
  82. // restore original font
  83. if (hOldFont)
  84. {
  85. ::SelectObject(hdc, hOldFont);
  86. }
  87. ::SetTextAlign(hdc, uiOldAlign);
  88. ::SetTextColor(hdc, crOldTextColor);
  89. ::SetBkMode(hdc, iOldBkMode);
  90. return hr;
  91. }
  92. /*************************************************************************/
  93. /* Function: GetTextWidth */
  94. /* Description: Get the width of text string based on the current font */
  95. /* and settings. */
  96. /*************************************************************************/
  97. HRESULT CText::GetTextWidth(HDC hdc, const WCHAR * pwszText, SIZE *pSize)
  98. {
  99. USES_CONVERSION;
  100. HRESULT hr = S_OK;
  101. const int cBorderMargin = 2; // 2 pixel margin on left or right border
  102. // create the required font
  103. if (m_fDirty)
  104. {
  105. hr = RealizeFont(hdc);
  106. }
  107. HFONT hOldFont = NULL;
  108. if (m_hFont)
  109. {
  110. hOldFont = (HFONT) ::SelectObject(hdc, m_hFont);
  111. }
  112. ::GetTextExtentPoint32(hdc, W2CT(pwszText), wcslen(pwszText), pSize);
  113. pSize->cx += 2*cBorderMargin;
  114. if (hOldFont)
  115. {
  116. ::SelectObject(hdc, hOldFont);
  117. }
  118. return hr;
  119. }
  120. /*************************************************************************/
  121. /* Function: RealizeFont */
  122. /* Description: create a font based on the current font style, size etc. */
  123. /* Cache the font. */
  124. /*************************************************************************/
  125. HRESULT CText::RealizeFont(HDC hdc)
  126. {
  127. USES_CONVERSION;
  128. HRESULT hr = S_OK;
  129. if( NULL != m_hFont)
  130. {
  131. ::DeleteObject(m_hFont);
  132. m_hFont = NULL;
  133. }
  134. // by default, font size changes with system font size which
  135. // depends on the system screen resolution
  136. int nPixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
  137. // if we fixed the font size, we assume always small font (96 pixels per inch)
  138. if (m_fFixedSizeFont)
  139. {
  140. nPixelsPerInch = 96;
  141. }
  142. int nHeight = -MulDiv(m_uiFontSize, nPixelsPerInch, 72);
  143. m_hFont = ::CreateFont(
  144. nHeight, // logical height of font
  145. 0, // logical average character width
  146. 0, // angle of escapement
  147. 0, // base-line orientation angle
  148. (m_fFontStyleFlags&FS_BOLD)?FW_BOLD:FW_NORMAL,// font weight
  149. (m_fFontStyleFlags&FS_ITALIC)?1:0, // italic attribute flag
  150. (m_fFontStyleFlags&FS_UNDERLINE)?1:0, // underline attribute flag
  151. (m_fFontStyleFlags&FS_STRIKEOUT)?1:0, // strikeout attribute flag
  152. DEFAULT_CHARSET, // character set identifier
  153. OUT_DEFAULT_PRECIS, // output precision
  154. CLIP_DEFAULT_PRECIS, // clipping precision
  155. ANTIALIASED_QUALITY, // output quality
  156. DEFAULT_PITCH, // pitch and family
  157. W2T(m_bstrFontFace.m_str) // pointer to typeface name string
  158. );
  159. if( NULL == m_hFont )
  160. {
  161. DWORD dwErr;
  162. dwErr = GetLastError();
  163. hr = HRESULT_FROM_WIN32(dwErr);
  164. }
  165. m_fDirty = false;
  166. return hr;
  167. }
  168. /*************************************************************************/
  169. /* Function: SetFontSize */
  170. /* Description: set the FontSize property, in pt. */
  171. /*************************************************************************/
  172. void CText::SetFontSize(long lSize)
  173. {
  174. if ((UINT)lSize != m_uiFontSize)
  175. {
  176. m_uiFontSize = (UINT)lSize;
  177. m_fDirty = true;
  178. }
  179. }
  180. /*************************************************************************/
  181. /* Function: SetFixedSizeFont */
  182. /* Description: set flag which indicates whether the font size is fixed */
  183. /* or variable with system font. */
  184. /*************************************************************************/
  185. void CText::SetFixedSizeFont(bool fFixed)
  186. {
  187. if (fFixed != m_fFixedSizeFont)
  188. {
  189. m_fFixedSizeFont = fFixed;
  190. m_fDirty = true;
  191. }
  192. }
  193. /*************************************************************************/
  194. /* Function: SetFontFace */
  195. /* Description: set the FontFace property. */
  196. /*************************************************************************/
  197. void CText::SetFontFace(BSTR pwszFontFace)
  198. {
  199. if (_wcsicmp(m_bstrFontFace, pwszFontFace) != 0)
  200. {
  201. m_bstrFontFace = pwszFontFace;
  202. m_fDirty = true;
  203. }
  204. }
  205. /*************************************************************************/
  206. /* Function: SetFontStyle */
  207. /* Description: set the FontStyle property. The style string should */
  208. /* contain either "Normal", or concatenation of one or more strings of: */
  209. /* "Bold", "Italic", "Underline", "Strikeout". Default is "Normal". */
  210. /*************************************************************************/
  211. void CText::SetFontStyle(BSTR pwszFontStyle)
  212. {
  213. BYTE fFontStyleFlags = FS_NORMAL;
  214. //find a match
  215. if( NULL != wcsstr(pwszFontStyle, L"Normal"))
  216. {
  217. fFontStyleFlags = FS_NORMAL;
  218. }
  219. else
  220. {
  221. // Turn on all styles that match
  222. if( NULL != wcsstr(pwszFontStyle, L"Bold"))
  223. {
  224. fFontStyleFlags |= FS_BOLD;
  225. }
  226. if( NULL != wcsstr(pwszFontStyle, L"Italic"))
  227. {
  228. fFontStyleFlags |= FS_ITALIC;
  229. }
  230. if( NULL != wcsstr(pwszFontStyle, L"Underline"))
  231. {
  232. fFontStyleFlags |= FS_UNDERLINE;
  233. }
  234. if( NULL != wcsstr(pwszFontStyle, L"Strikeout"))
  235. {
  236. fFontStyleFlags |= FS_STRIKEOUT;
  237. }
  238. }
  239. if (fFontStyleFlags != m_fFontStyleFlags)
  240. {
  241. m_fFontStyleFlags = fFontStyleFlags;
  242. m_bstrFontStyle = pwszFontStyle;
  243. m_fDirty = true;
  244. }
  245. }
  246. /*************************************************************************/
  247. /* Function: SetFontSize */
  248. /* Description: set the FontSize property, in pt. */
  249. /*************************************************************************/
  250. void CText::SetTextColor(COLORREF clrColor)
  251. {
  252. if (clrColor != m_clrTextColor)
  253. {
  254. m_clrTextColor = clrColor;
  255. }
  256. }
  257. /*************************************************************************/
  258. /* Function: SetTextAlignment */
  259. /* Description: set the TextAlignment property. It controls the */
  260. /* horizontal text alignment. Must be one of "Left", "Center", or */
  261. /* "Right". Default is "Center". */
  262. /*************************************************************************/
  263. void CText::SetTextAlignment(BSTR pwszAlignment)
  264. {
  265. UINT uiAlignment = 0;
  266. //set the text alignment
  267. if (!_wcsicmp(pwszAlignment, L"Right"))
  268. {
  269. uiAlignment = TA_RIGHT;
  270. }
  271. else if (!_wcsicmp(pwszAlignment, L"Center"))
  272. {
  273. uiAlignment = TA_CENTER;
  274. }
  275. else if (!_wcsicmp(pwszAlignment, L"Left"))
  276. {
  277. uiAlignment = TA_LEFT;
  278. }
  279. if (m_uiAlignment != uiAlignment)
  280. {
  281. m_uiAlignment = uiAlignment;
  282. }
  283. }