/*************************************************************************/ /* Copyright (C) 1999 Microsoft Corporation */ /* File: ctext.cpp */ /* Description: Implementation of ctext class for drawing text. */ /* Author: phillu */ /* Date: 10/06/99 */ /*************************************************************************/ #include "stdafx.h" #include "ctext.h" /*************************************************************************/ /* Function: CText::CText() */ /* Description: Initialize the properties and states. */ /*************************************************************************/ CText::CText() { m_fDirty = true; m_hFont = NULL; //properties m_uiFontSize = 10; m_uiAlignment = TA_CENTER; m_clrTextColor = GetSysColor(COLOR_WINDOWTEXT); m_bstrFontFace = L"Arial"; m_bstrFontStyle = L"Normal"; m_fFontStyleFlags = FS_NORMAL; m_fFixedSizeFont = false; } /*************************************************************************/ /* Function: CText::~CText() */ /* Description: Destroy the cached font. */ /*************************************************************************/ CText::~CText() { if (m_hFont) { ::DeleteObject(m_hFont); m_hFont = NULL; } } /*************************************************************************/ /* Function: Write */ /* Description: Draw text in the specified rectangle. */ /* The font is not created until drawing text for the first time. */ /* Assume the following settings: */ /* - Use Transparent background mode; no change of bg color */ /* - Vertical alignment is always centered */ /*************************************************************************/ HRESULT CText::Write(HDC hdc, const RECT & rc, const WCHAR * pwszText) { USES_CONVERSION; HRESULT hr = S_OK; const int cBorderMargin = 2; // 2 pixel margin on left or right border // set drawing attributes, save the old ones UINT uiOldAlign = ::SetTextAlign(hdc, m_uiAlignment|TA_BOTTOM); COLORREF crOldTextColor = ::SetTextColor(hdc, m_clrTextColor); int iOldBkMode = ::SetBkMode(hdc, TRANSPARENT); // create the required font if (m_fDirty) { hr = RealizeFont(hdc); } HFONT hOldFont = NULL; if (m_hFont) { hOldFont = (HFONT) ::SelectObject(hdc, m_hFont); } // set position of text based on alignment TEXTMETRIC tm; GetTextMetrics(hdc, &tm); int x = (rc.left + rc.right)/2; if (m_uiAlignment == TA_LEFT) { x = rc.left + cBorderMargin; } else if (m_uiAlignment == TA_RIGHT) { x = rc.right - cBorderMargin; } // text is aligned at the bottom. Adding half of text height makes // it to position at the center vertically int y = (rc.top + rc.bottom)/2 + tm.tmHeight/2; LPCTSTR strTemp = W2CT(pwszText); int nLength = _tcslen(strTemp); if (NULL == strTemp) { hr = E_POINTER; } else { ::TextOut(hdc, x, y, strTemp, nLength); } // restore original font if (hOldFont) { ::SelectObject(hdc, hOldFont); } ::SetTextAlign(hdc, uiOldAlign); ::SetTextColor(hdc, crOldTextColor); ::SetBkMode(hdc, iOldBkMode); return hr; } /*************************************************************************/ /* Function: GetTextWidth */ /* Description: Get the width of text string based on the current font */ /* and settings. */ /*************************************************************************/ HRESULT CText::GetTextWidth(HDC hdc, const WCHAR * pwszText, SIZE *pSize) { USES_CONVERSION; HRESULT hr = S_OK; const int cBorderMargin = 2; // 2 pixel margin on left or right border // create the required font if (m_fDirty) { hr = RealizeFont(hdc); } HFONT hOldFont = NULL; if (m_hFont) { hOldFont = (HFONT) ::SelectObject(hdc, m_hFont); } LPCTSTR strTemp = W2CT(pwszText); int nLength = _tcslen(strTemp); if (NULL == strTemp) // guard agaist a NULL pointer { hr = E_POINTER; } else { ::GetTextExtentPoint32(hdc, strTemp, nLength, pSize); pSize->cx += 2*cBorderMargin; } if (hOldFont) { ::SelectObject(hdc, hOldFont); } return hr; } /*************************************************************************/ /* Function: RealizeFont */ /* Description: create a font based on the current font style, size etc. */ /* Cache the font. */ /*************************************************************************/ HRESULT CText::RealizeFont(HDC hdc) { USES_CONVERSION; HRESULT hr = S_OK; if( NULL != m_hFont) { ::DeleteObject(m_hFont); m_hFont = NULL; } // by default, font size changes with system font size which // depends on the system screen resolution int nPixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY); // if we fixed the font size, we assume always small font (96 pixels per inch) if (m_fFixedSizeFont) { nPixelsPerInch = 96; } int nHeight = -MulDiv(m_uiFontSize, nPixelsPerInch, 72); m_hFont = ::CreateFont( nHeight, // logical height of font 0, // logical average character width 0, // angle of escapement 0, // base-line orientation angle (m_fFontStyleFlags&FS_BOLD)?FW_BOLD:FW_NORMAL,// font weight (m_fFontStyleFlags&FS_ITALIC)?1:0, // italic attribute flag (m_fFontStyleFlags&FS_UNDERLINE)?1:0, // underline attribute flag (m_fFontStyleFlags&FS_STRIKEOUT)?1:0, // strikeout attribute flag DEFAULT_CHARSET, // character set identifier OUT_DEFAULT_PRECIS, // output precision CLIP_DEFAULT_PRECIS, // clipping precision ANTIALIASED_QUALITY, // output quality DEFAULT_PITCH, // pitch and family W2T(m_bstrFontFace.m_str) // pointer to typeface name string ); if( NULL == m_hFont ) { DWORD dwErr; dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); } m_fDirty = false; return hr; } /*************************************************************************/ /* Function: SetFontSize */ /* Description: set the FontSize property, in pt. */ /*************************************************************************/ void CText::SetFontSize(long lSize) { if ((UINT)lSize != m_uiFontSize) { m_uiFontSize = (UINT)lSize; m_fDirty = true; } } /*************************************************************************/ /* Function: SetFixedSizeFont */ /* Description: set flag which indicates whether the font size is fixed */ /* or variable with system font. */ /*************************************************************************/ void CText::SetFixedSizeFont(bool fFixed) { if (fFixed != m_fFixedSizeFont) { m_fFixedSizeFont = fFixed; m_fDirty = true; } } /*************************************************************************/ /* Function: SetFontFace */ /* Description: set the FontFace property. */ /*************************************************************************/ void CText::SetFontFace(BSTR pwszFontFace) { if (_wcsicmp(m_bstrFontFace, pwszFontFace) != 0) { m_bstrFontFace = pwszFontFace; m_fDirty = true; } } /*************************************************************************/ /* Function: SetFontStyle */ /* Description: set the FontStyle property. The style string should */ /* contain either "Normal", or concatenation of one or more strings of: */ /* "Bold", "Italic", "Underline", "Strikeout". Default is "Normal". */ /*************************************************************************/ void CText::SetFontStyle(BSTR pwszFontStyle) { BYTE fFontStyleFlags = FS_NORMAL; //find a match if( NULL != wcsstr(pwszFontStyle, L"Normal")) { fFontStyleFlags = FS_NORMAL; } else { // Turn on all styles that match if( NULL != wcsstr(pwszFontStyle, L"Bold")) { fFontStyleFlags |= FS_BOLD; } if( NULL != wcsstr(pwszFontStyle, L"Italic")) { fFontStyleFlags |= FS_ITALIC; } if( NULL != wcsstr(pwszFontStyle, L"Underline")) { fFontStyleFlags |= FS_UNDERLINE; } if( NULL != wcsstr(pwszFontStyle, L"Strikeout")) { fFontStyleFlags |= FS_STRIKEOUT; } } if (fFontStyleFlags != m_fFontStyleFlags) { m_fFontStyleFlags = fFontStyleFlags; m_bstrFontStyle = pwszFontStyle; m_fDirty = true; } } /*************************************************************************/ /* Function: SetFontSize */ /* Description: set the FontSize property, in pt. */ /*************************************************************************/ void CText::SetTextColor(COLORREF clrColor) { if (clrColor != m_clrTextColor) { m_clrTextColor = clrColor; } } /*************************************************************************/ /* Function: SetTextAlignment */ /* Description: set the TextAlignment property. It controls the */ /* horizontal text alignment. Must be one of "Left", "Center", or */ /* "Right". Default is "Center". */ /*************************************************************************/ void CText::SetTextAlignment(BSTR pwszAlignment) { UINT uiAlignment = 0; //set the text alignment if (!_wcsicmp(pwszAlignment, L"Right")) { uiAlignment = TA_RIGHT; } else if (!_wcsicmp(pwszAlignment, L"Center")) { uiAlignment = TA_CENTER; } else if (!_wcsicmp(pwszAlignment, L"Left")) { uiAlignment = TA_LEFT; } if (m_uiAlignment != uiAlignment) { m_uiAlignment = uiAlignment; } }