📄 nghtmlstaticctrl.cpp
字号:
// XHTMLStatic.cpp Version 1.0
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// 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
//
// This software is released into the public domain.
// You are free to use it in any way you like.
//
// 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 "NGHtmlStaticCtrl.h"
#include "NGNamedColours.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//#define _THEME
#ifdef _THEME
#include <Uxtheme.h>
#include <tmschema.h>
#pragma comment(lib, "UxTheme.lib")
#endif
///////////////////////////////////////////////////////////////////////////////
// CNGHtmlStaticCtrl
BEGIN_MESSAGE_MAP(CNGHtmlStaticCtrl, CStatic)
//{{AFX_MSG_MAP(CNGHtmlStaticCtrl)
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_TIMER()
ON_WM_SETCURSOR()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SETTEXT, OnMsgSetText)
ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
// ctor
CNGHtmlStaticCtrl::CNGHtmlStaticCtrl()
{
m_crBackGround = CLR_DEFAULT;
m_crText = ::GetSysColor(COLOR_WINDOWTEXT);
m_bTransparent = FALSE;
m_bUnderline = FALSE;
m_bBold = FALSE;
m_bItalic = FALSE;
m_bStrikeThrough = FALSE;
m_bHyperlinkTimer = FALSE;
m_bOnHyperlink = FALSE;
m_hLinkCursor = NULL;
m_hPrevCursor = NULL;
m_bInAnchor = FALSE;
m_AnchorRectPtrs.RemoveAll();
m_AnchorUrls.RemoveAll();
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);
}
///////////////////////////////////////////////////////////////////////////////
// dtor
CNGHtmlStaticCtrl::~CNGHtmlStaticCtrl()
{
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();
}
int CNGHtmlStaticCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
int nResult = CStatic::OnCreate(lpCreateStruct);
if (nResult != -1)
{
// We want to get mouse clicks via STN_CLICKED
DWORD dwStyle = GetStyle();
::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);
DWORD dwStyleEx = GetExStyle();
m_bTransparent = ( (dwStyleEx & WS_EX_TRANSPARENT) > 0);
CFont* cf = GetFont();
LOGFONT lf;
if (cf != NULL)
{
cf->GetObject(sizeof(lf), &lf);
}
else
{
GetObject(GetStockObject(SYSTEM_FONT), sizeof(lf), &lf);
}
m_font.DeleteObject();
VERIFY(m_font.CreateFontIndirect(&lf));
}
return nResult;
}
BOOL CNGHtmlStaticCtrl::OnEraseBkgnd(CDC* pDC)
{
if (!m_bTransparent && (m_crBackGround != CLR_DEFAULT) )
{
CRect rect;
GetClientRect(&rect);
pDC->FillSolidRect(&rect, m_crBackGround);
return TRUE;
}
return CStatic::OnEraseBkgnd(pDC);
}
LRESULT CNGHtmlStaticCtrl::OnMsgSetText(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
Invalidate();
return Default();
}
void CNGHtmlStaticCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
// get text from control
CString strText;
GetWindowText(strText);
// Reset these flags just in case the HTML was badly formed and
// we were left hanging...
m_bBold = FALSE;
m_bUnderline = FALSE;
m_bItalic = FALSE;
m_bStrikeThrough = FALSE;
CString str1;
int index;
// 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);
/* if (!m_bTransparent)
{
dc.FillSolidRect(&rect, m_crBackGround);
}
*/
int nInitialXOffset = 0;
LOGFONT lf, prev_lf;
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("");
while (n > 0)
{
///////////////////////////////////////////////////////////////////////
if (strText.Left(3) == _T("<b>") || // check for <b>
strText.Left(3) == _T("<B>")) // check for <B>
{
n -= 3;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bBold++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (strText.Left(4) == _T("</b>") || // check for </b>
strText.Left(4) == _T("</B>")) // 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 (strText.Left(3) == _T("<i>") || // check for <i>
strText.Left(3) == _T("<I>")) // check for <I>
{
n -= 3;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bItalic++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (strText.Left(4) == _T("</i>") || // check for </i>
strText.Left(4) == _T("</I>")) // 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 (strText.Left(3) == _T("<u>") || // check for <u>
strText.Left(3) == _T("<U>")) // check for <U>
{
n -= 3;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bUnderline++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (strText.Left(4) == _T("</u>") || // check for </u>
strText.Left(4) == _T("</U>")) // 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 (strText.Left(8) == _T("<strike>") || // check for <strike>
strText.Left(8) == _T("<STRIKE>")) // check for <STRIKE>
{
n -= 8;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
m_bStrikeThrough++;// = TRUE;
continue;
}
///////////////////////////////////////////////////////////////////////
else if (strText.Left(9) == _T("</strike>") || // check for </strike>
strText.Left(9) == _T("</STRIKE>")) // 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 (strText.Left(5) == _T("<font") || // check for <font
strText.Left(5) == _T("<FONT")) // check for <FONT
{
index = strText.Find(_T('>'));
if (index != -1)
{
CString strFont = strText.Mid(5, index-5);
int m = strFont.GetLength();
strText = strText.Mid(index+1);
// loop to parse FONT attributes
while (m > 0)
{
// trim left whitespace
if ((strFont.GetLength() > 0) && (strFont[0] == _T(' ')))
{
m--;
strFont = strFont.Mid(1);
continue;
}
///////////////////////////////////////////////////////////
if (strFont.Left(5) == _T("color") ||
strFont.Left(5) == _T("COLOR"))
{
int index2 = strFont.Find(_T('"'));
if (index2 != -1)
{
m -= index2 + 1;
strFont = strFont.Mid(index2+1);
index2 = strFont.Find(_T('"'));
if (index2 != -1)
{
CString strColor = strFont.Left(index2);
CNGNamedColours nc(strColor);
crText = nc.GetRGB();
strFont = strFont.Mid(index2+1);
m = strFont.GetLength();
}
}
else
break;
}
///////////////////////////////////////////////////////////
else if (strFont.Left(7) == _T("bgcolor") ||
strFont.Left(7) == _T("BGCOLOR"))
{
int index2 = strFont.Find(_T('"'));
if (index2 != -1)
{
m -= index2 + 1;
strFont = strFont.Mid(index2+1);
index2 = strFont.Find(_T('"'));
if (index2 != -1)
{
CString strBgColor = strFont.Left(index2);
CNGNamedColours nc(strBgColor);
crBackground = nc.GetRGB();
strFont = strFont.Mid(index2+1);
m = strFont.GetLength();
}
}
else
break;
}
///////////////////////////////////////////////////////////
else if (strFont.Left(4) == _T("face") ||
strFont.Left(4) == _T("FACE"))
{
int index2 = strFont.Find(_T('"'));
if (index2 != -1)
{
m -= index2 + 1;
strFont = strFont.Mid(index2+1);
index2 = strFont.Find(_T('"'));
if (index2 != -1)
{
memset(lf.lfFaceName, 0, sizeof(lf.lfFaceName));
_tcsncpy(lf.lfFaceName, strFont, index2);
m -= index2 + 1;
if (m > 0)
strFont = strFont.Mid(index2+1);
else
strFont = _T("");
m = strFont.GetLength();
}
}
else
break;
}
///////////////////////////////////////////////////////////
else if (strFont.Left(4) == _T("size") ||
strFont.Left(4) == _T("SIZE"))
{
int index2 = strFont.Find(_T('"'));
if (index2 != -1)
{
m -= index2 + 1;
strFont = strFont.Mid(index2+1);
index2 = strFont.Find(_T('"'));
if (index2 != -1)
{
int nSize = 0;
nSize = _ttoi(strFont);
lf.lfHeight -= nSize;
m -= index2 + 1;
if (m > 0)
strFont = strFont.Mid(index2+1);
else
strFont = _T("");
m = strFont.GetLength();
}
}
else
break;
}
else
{
while ((strFont.GetLength() > 0) &&
(strFont[0] != _T(' ')))
{
m--;
strFont = strFont.Mid(1);
}
}
}
n -= index + 1;
}
continue;
}
///////////////////////////////////////////////////////////////////////
else if (strText.Left(7) == _T("</font>") || // check for </font>
strText.Left(7) == _T("</FONT>")) // check for </FONT>
{
n -= 7;
index = strText.Find(_T('>'));
if (index != -1)
strText = strText.Mid(index+1);
crText = prev_crText;
crBackground = prev_crBackground;
memcpy(&lf, &prev_lf, sizeof(lf));
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -