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.

361 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. LPCTSTR strTemp = W2CT(pwszText);
  82. int nLength = _tcslen(strTemp);
  83. if (NULL == strTemp)
  84. {
  85. hr = E_POINTER;
  86. }
  87. else
  88. {
  89. ::TextOut(hdc, x, y, strTemp, nLength);
  90. }
  91. // restore original font
  92. if (hOldFont)
  93. {
  94. ::SelectObject(hdc, hOldFont);
  95. }
  96. ::SetTextAlign(hdc, uiOldAlign);
  97. ::SetTextColor(hdc, crOldTextColor);
  98. ::SetBkMode(hdc, iOldBkMode);
  99. return hr;
  100. }
  101. /*************************************************************************/
  102. /* Function: GetTextWidth */
  103. /* Description: Get the width of text string based on the current font */
  104. /* and settings. */
  105. /*************************************************************************/
  106. HRESULT CText::GetTextWidth(HDC hdc, const WCHAR * pwszText, SIZE *pSize)
  107. {
  108. USES_CONVERSION;
  109. HRESULT hr = S_OK;
  110. const int cBorderMargin = 2; // 2 pixel margin on left or right border
  111. // create the required font
  112. if (m_fDirty)
  113. {
  114. hr = RealizeFont(hdc);
  115. }
  116. HFONT hOldFont = NULL;
  117. if (m_hFont)
  118. {
  119. hOldFont = (HFONT) ::SelectObject(hdc, m_hFont);
  120. }
  121. LPCTSTR strTemp = W2CT(pwszText);
  122. int nLength = _tcslen(strTemp);
  123. if (NULL == strTemp) // guard agaist a NULL pointer
  124. {
  125. hr = E_POINTER;
  126. }
  127. else
  128. {
  129. ::GetTextExtentPoint32(hdc, strTemp, nLength, pSize);
  130. pSize->cx += 2*cBorderMargin;
  131. }
  132. if (hOldFont)
  133. {
  134. ::SelectObject(hdc, hOldFont);
  135. }
  136. return hr;
  137. }
  138. /*************************************************************************/
  139. /* Function: RealizeFont */
  140. /* Description: create a font based on the current font style, size etc. */
  141. /* Cache the font. */
  142. /*************************************************************************/
  143. HRESULT CText::RealizeFont(HDC hdc)
  144. {
  145. USES_CONVERSION;
  146. HRESULT hr = S_OK;
  147. if( NULL != m_hFont)
  148. {
  149. ::DeleteObject(m_hFont);
  150. m_hFont = NULL;
  151. }
  152. // by default, font size changes with system font size which
  153. // depends on the system screen resolution
  154. int nPixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
  155. // if we fixed the font size, we assume always small font (96 pixels per inch)
  156. if (m_fFixedSizeFont)
  157. {
  158. nPixelsPerInch = 96;
  159. }
  160. int nHeight = -MulDiv(m_uiFontSize, nPixelsPerInch, 72);
  161. m_hFont = ::CreateFont(
  162. nHeight, // logical height of font
  163. 0, // logical average character width
  164. 0, // angle of escapement
  165. 0, // base-line orientation angle
  166. (m_fFontStyleFlags&FS_BOLD)?FW_BOLD:FW_NORMAL,// font weight
  167. (m_fFontStyleFlags&FS_ITALIC)?1:0, // italic attribute flag
  168. (m_fFontStyleFlags&FS_UNDERLINE)?1:0, // underline attribute flag
  169. (m_fFontStyleFlags&FS_STRIKEOUT)?1:0, // strikeout attribute flag
  170. DEFAULT_CHARSET, // character set identifier
  171. OUT_DEFAULT_PRECIS, // output precision
  172. CLIP_DEFAULT_PRECIS, // clipping precision
  173. ANTIALIASED_QUALITY, // output quality
  174. DEFAULT_PITCH, // pitch and family
  175. W2T(m_bstrFontFace.m_str) // pointer to typeface name string
  176. );
  177. if( NULL == m_hFont )
  178. {
  179. DWORD dwErr;
  180. dwErr = GetLastError();
  181. hr = HRESULT_FROM_WIN32(dwErr);
  182. }
  183. m_fDirty = false;
  184. return hr;
  185. }
  186. /*************************************************************************/
  187. /* Function: SetFontSize */
  188. /* Description: set the FontSize property, in pt. */
  189. /*************************************************************************/
  190. void CText::SetFontSize(long lSize)
  191. {
  192. if ((UINT)lSize != m_uiFontSize)
  193. {
  194. m_uiFontSize = (UINT)lSize;
  195. m_fDirty = true;
  196. }
  197. }
  198. /*************************************************************************/
  199. /* Function: SetFixedSizeFont */
  200. /* Description: set flag which indicates whether the font size is fixed */
  201. /* or variable with system font. */
  202. /*************************************************************************/
  203. void CText::SetFixedSizeFont(bool fFixed)
  204. {
  205. if (fFixed != m_fFixedSizeFont)
  206. {
  207. m_fFixedSizeFont = fFixed;
  208. m_fDirty = true;
  209. }
  210. }
  211. /*************************************************************************/
  212. /* Function: SetFontFace */
  213. /* Description: set the FontFace property. */
  214. /*************************************************************************/
  215. void CText::SetFontFace(BSTR pwszFontFace)
  216. {
  217. if (_wcsicmp(m_bstrFontFace, pwszFontFace) != 0)
  218. {
  219. m_bstrFontFace = pwszFontFace;
  220. m_fDirty = true;
  221. }
  222. }
  223. /*************************************************************************/
  224. /* Function: SetFontStyle */
  225. /* Description: set the FontStyle property. The style string should */
  226. /* contain either "Normal", or concatenation of one or more strings of: */
  227. /* "Bold", "Italic", "Underline", "Strikeout". Default is "Normal". */
  228. /*************************************************************************/
  229. void CText::SetFontStyle(BSTR pwszFontStyle)
  230. {
  231. BYTE fFontStyleFlags = FS_NORMAL;
  232. //find a match
  233. if( NULL != wcsstr(pwszFontStyle, L"Normal"))
  234. {
  235. fFontStyleFlags = FS_NORMAL;
  236. }
  237. else
  238. {
  239. // Turn on all styles that match
  240. if( NULL != wcsstr(pwszFontStyle, L"Bold"))
  241. {
  242. fFontStyleFlags |= FS_BOLD;
  243. }
  244. if( NULL != wcsstr(pwszFontStyle, L"Italic"))
  245. {
  246. fFontStyleFlags |= FS_ITALIC;
  247. }
  248. if( NULL != wcsstr(pwszFontStyle, L"Underline"))
  249. {
  250. fFontStyleFlags |= FS_UNDERLINE;
  251. }
  252. if( NULL != wcsstr(pwszFontStyle, L"Strikeout"))
  253. {
  254. fFontStyleFlags |= FS_STRIKEOUT;
  255. }
  256. }
  257. if (fFontStyleFlags != m_fFontStyleFlags)
  258. {
  259. m_fFontStyleFlags = fFontStyleFlags;
  260. m_bstrFontStyle = pwszFontStyle;
  261. m_fDirty = true;
  262. }
  263. }
  264. /*************************************************************************/
  265. /* Function: SetFontSize */
  266. /* Description: set the FontSize property, in pt. */
  267. /*************************************************************************/
  268. void CText::SetTextColor(COLORREF clrColor)
  269. {
  270. if (clrColor != m_clrTextColor)
  271. {
  272. m_clrTextColor = clrColor;
  273. }
  274. }
  275. /*************************************************************************/
  276. /* Function: SetTextAlignment */
  277. /* Description: set the TextAlignment property. It controls the */
  278. /* horizontal text alignment. Must be one of "Left", "Center", or */
  279. /* "Right". Default is "Center". */
  280. /*************************************************************************/
  281. void CText::SetTextAlignment(BSTR pwszAlignment)
  282. {
  283. UINT uiAlignment = 0;
  284. //set the text alignment
  285. if (!_wcsicmp(pwszAlignment, L"Right"))
  286. {
  287. uiAlignment = TA_RIGHT;
  288. }
  289. else if (!_wcsicmp(pwszAlignment, L"Center"))
  290. {
  291. uiAlignment = TA_CENTER;
  292. }
  293. else if (!_wcsicmp(pwszAlignment, L"Left"))
  294. {
  295. uiAlignment = TA_LEFT;
  296. }
  297. if (m_uiAlignment != uiAlignment)
  298. {
  299. m_uiAlignment = uiAlignment;
  300. }
  301. }