xhtmlstatic.cpp
来自「管理项目进度工具的原代码」· C++ 代码 · 共 1,326 行 · 第 1/3 页
CPP
1,326 行
// XHTMLStatic.cpp Version 1.2
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// History
// Version 1.2 - 2004 June 12
// - Changed APP: hyperlink to use HWND instead of GetParent();
// - Added wParam to XHTMLSTATIC_APP_COMMAND struct
// - Added function SetTextColor(LPCTSTR lpszColor)
// - Added function SetLogFont(const LOGFONT * pLogFont)
// - Added function SetWindowText() to call Init and RedrawWindow
// - Fixed bug with XNamedColors in handling of "255,0,0" style
// in SetColorFromString()
// - Fixed bug with descenders of large serif fonts
//
// Version 1.1 - 2004 May 20
// - Implemented SUB tag
// - Implemented SUP tag
// - Implemented BIG tag
// - Implemented SMALL tag
// - Implemented CODE tag
// - Implemented HR tag
// - Implemented APP: hyperlink
// - Implemented common character entities
// - Improved parsing performance
// - Bug fixes
//
// Version 1.0 - 2002 September 16
// - Initial public release
//
// Acknowledgements:
// Thanks to Charles Petzold for explaining how GetTextExtentPoint32()
// works, in his excellent "Programming Windows", Fifth Edition:
// http://www.bookpool.com/.x/6o8gzz6xw6/sm/157231995X
//
// Thanks to Chris Maunder for showing how to set the cursor and receive
// mouse clicks for static controls, and for all the code that I used
// from his CHyperLink class:
// http://www.codeproject.com/miscctrl/hyperlink.asp
//
// License:
// This software is released into the public domain. You are free to use
// it in any way you like, except that you may not sell this source code.
//
// This software is provided "as is" with no expressed or implied warranty.
// I accept no liability for any damage or loss of business that this
// software may cause.
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XHTMLStatic.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// some common character entities
XHTMLSTATIC_CHAR_ENTITIES CXHTMLStatic::m_aCharEntities[] =
{
{ _T("&"), 0, _T('&') }, // ampersand
{ _T("•"), 0, _T('\x95') }, // bullet NOT IN MS SANS SERIF
{ _T("©"), 0, _T('\xA9') }, // copyright
{ _T("€"), 0, _T('\x80') }, // euro sign
{ _T(">"), 0, _T('>') }, // greater than
{ _T("¿"), 0, _T('\xBF') }, // inverted question mark
{ _T("<"), 0, _T('<') }, // less than
{ _T(" "), 0, _T(' ') }, // nonbreaking space
{ _T("¶"), 0, _T('\xB6') }, // paragraph sign
{ _T("£"), 0, _T('\xA3') }, // pound sign
{ _T("""), 0, _T('"') }, // quotation mark
{ _T("®"), 0, _T('\xAE') }, // registered trademark
{ _T("™"), 0, _T('\x99') }, // trademark NOT IN MS SANS SERIF
{ NULL, 0, 0 } // MUST BE LAST
};
///////////////////////////////////////////////////////////////////////////////
// CXHTMLStatic
#define WM_SHOWACCELERATORS 0x0128
BEGIN_MESSAGE_MAP(CXHTMLStatic, CStatic)
//{{AFX_MSG_MAP(CXHTMLStatic)
ON_WM_PAINT()
ON_WM_TIMER()
ON_WM_SETCURSOR()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
ON_MESSAGE(WM_SHOWACCELERATORS, OnShowAccelerators)
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
// ctor
CXHTMLStatic::CXHTMLStatic()
{
memset(&m_lf, 0, sizeof(m_lf));
m_bLogFont = FALSE;
m_hLinkCursor = NULL;
m_paAppCommands = NULL;
m_nAppCommands = 0;
m_nLeftMargin = 0;
m_nRightMargin = 0;
m_AnchorRectPtrs.RemoveAll();
m_AnchorUrls.RemoveAll();
// get hand cursor
CString strWndDir;
GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
strWndDir.ReleaseBuffer();
strWndDir += _T("\\winhlp32.exe");
// This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
HMODULE hModule = ::LoadLibrary(strWndDir);
if (hModule)
{
HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
if (hHandCursor)
m_hLinkCursor = CopyCursor(hHandCursor);
}
::FreeLibrary(hModule);
InitCharEntities();
Init();
}
///////////////////////////////////////////////////////////////////////////////
// dtor
CXHTMLStatic::~CXHTMLStatic()
{
Init();
if (m_hLinkCursor)
::DestroyCursor(m_hLinkCursor);
m_hLinkCursor = NULL;
if (m_paAppCommands)
delete [] m_paAppCommands;
m_paAppCommands = NULL;
}
///////////////////////////////////////////////////////////////////////////////
// InitCharEntities
void CXHTMLStatic::InitCharEntities()
{
for (int i = 0; m_aCharEntities[i].pszName != NULL; i++)
{
m_aCharEntities[i].cCode = (TCHAR) (i + 2); // don't use 0 or 1
}
}
///////////////////////////////////////////////////////////////////////////////
// InitCharEntities
TCHAR CXHTMLStatic::GetCharEntity(TCHAR cCode)
{
TCHAR c = _T(' ');
for (int i = 0; m_aCharEntities[i].pszName != NULL; i++)
{
if (cCode == m_aCharEntities[i].cCode)
{
c = m_aCharEntities[i].cSymbol;
break;
}
}
return c;
}
///////////////////////////////////////////////////////////////////////////////
// Init
void CXHTMLStatic::Init()
{
m_crBackGround = ::GetSysColor(COLOR_WINDOW);
m_crText = ::GetSysColor(COLOR_WINDOWTEXT);
m_bUnderline = FALSE;
m_bBold = FALSE;
m_bItalic = FALSE;
m_bStrikeThrough = FALSE;
m_bSubscript = FALSE;
m_bSuperscript = FALSE;
m_bHorizontalRule = FALSE;
m_nHorizontalRuleSize = 2;
m_bHyperlinkTimer = FALSE;
m_bOnHyperlink = FALSE;
m_hPrevCursor = NULL;
m_bInAnchor = FALSE;
m_bGeneratedText = FALSE;
int n = m_AnchorRectPtrs.GetSize();
for (int i = 0; i < n; i++)
{
CRect *pRect = (CRect *) m_AnchorRectPtrs[i];
if (pRect)
delete pRect;
}
m_AnchorRectPtrs.RemoveAll();
m_AnchorUrls.RemoveAll();
}
///////////////////////////////////////////////////////////////////////////////
// OnPaint
void CXHTMLStatic::OnPaint()
{
CPaintDC dc(this); // device context for painting
// get text from control
CString strText = _T("");
GetWindowText(strText);
// replace character entity names with codes
TCHAR ent[3] = { 0 };
ent[0] = _T('\001'); // each entity name is replaced with a two-character
// code that begins with \001
for (int i = 0; m_aCharEntities[i].pszName != NULL; i++)
{
ent[1] = m_aCharEntities[i].cCode;
strText.Replace(m_aCharEntities[i].pszName, ent);
}
CString str1 = _T("");
int index = 0;
// set text and background colors
COLORREF crText = m_crText;
COLORREF prev_crText = crText;
COLORREF crBackground = m_crBackGround;
COLORREF prev_crBackground = crBackground;
CFont *pOldFont = dc.SelectObject(&m_font);
int n = strText.GetLength();
CRect rect;
GetClientRect(&rect);
dc.FillSolidRect(&rect, m_crBackGround);
// allow for margins
rect.left += m_nLeftMargin;
rect.right -= m_nRightMargin;
int nInitialXOffset = 0;//m_nLeftMargin;
m_yStart = rect.top;
LOGFONT lf, prev_lf;
if (m_bLogFont)
{
memcpy(&lf, &m_lf, sizeof(lf));
}
else
{
CFont* cf = GetFont();
if (cf)
cf->GetObject(sizeof(lf), &lf);
else
GetObject(GetStockObject(SYSTEM_FONT), sizeof(lf), &lf);
}
memcpy(&prev_lf, &lf, sizeof(lf));
CString strAnchorText = _T("");
BOOL bSizeChange = FALSE;
//BOOL bEndOfSizeChange = FALSE;
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
while (n > 0)
{
///////////////////////////////////////////////////////////////////////
if (_tcsnicmp(strText, _T("<B>"), 3) == 0) // check for <b> or <B>
{
n -= 3;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bBold++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("</B>"), 4) == 0) // check for </B>
{
n -= 4;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (m_bBold)
m_bBold--;// = FALSE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("<I>"), 3) == 0) // check for <I>
{
n -= 3;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bItalic++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("</I>"), 4) == 0) // check for </I>
{
n -= 4;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (m_bItalic)
m_bItalic--;// = FALSE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("<U>"), 3) == 0) // check for <U>
{
n -= 3;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bUnderline++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("</U>"), 4) == 0) // check for </U>
{
n -= 4;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (m_bUnderline)
m_bUnderline--;// = FALSE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("<STRIKE>"), 8) == 0) // check for <STRIKE>
{
n -= 8;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bStrikeThrough++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("</STRIKE>"), 9) == 0) // check for </STRIKE>
{
n -= 9;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (m_bStrikeThrough)
m_bStrikeThrough--;// = FALSE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("<BIG>"), 5) == 0) // check for <BIG>
{
n -= 5;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (lf.lfHeight > 0)
lf.lfHeight++;
else
lf.lfHeight--;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("</BIG>"), 6) == 0) // check for </BIG>
{
n -= 6;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (lf.lfHeight > 0)
lf.lfHeight--;
else
lf.lfHeight++;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("<SMALL>"), 7) == 0) // check for <SMALL>
{
n -= 7;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (lf.lfHeight > 0)
lf.lfHeight--;
else
lf.lfHeight++;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("</SMALL>"), 8) == 0) // check for </SMALL>
{
n -= 8;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (lf.lfHeight > 0)
lf.lfHeight++;
else
lf.lfHeight--;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("<SUB>"), 5) == 0) // check for <SUB>
{
n -= 5;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bSubscript++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("</SUB>"), 6) == 0) // check for </SUB>
{
n -= 6;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
if (m_bSubscript)
m_bSubscript--;// = FALSE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(strText, _T("<SUP>"), 5) == 0) // check for <SUP>
{
n -= 5;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?