📄 xhtmldraw.cpp
字号:
else if (_tcsnicmp(szAttributes, _T("FACE"), 4) == 0)
{
TCHAR *cp2 = _tcschr(szAttributes, _T('"'));
if (cp2)
{
m -= cp2 - szAttributes + 1;
_tcscpy(szAttributes, cp2+1);
cp2 = _tcschr(szAttributes, _T('"'));
if (cp2)
{
const int nFaceSize = sizeof(lf.lfFaceName); // in bytes
int nMaxFaceSize = nFaceSize / sizeof(TCHAR); // in TCHARs
memset(lf.lfFaceName, 0, nFaceSize);
int nNewFaceSize = (int)(cp2 - szAttributes); // in TCHARs
memset(&lf.lfFaceName, 0, nFaceSize);
_tcsncpy(lf.lfFaceName, szAttributes,
(nNewFaceSize > nMaxFaceSize) ? nMaxFaceSize : nNewFaceSize);
TRACE(_T("lf.lfFaceName=<%s>\n"), lf.lfFaceName);
m -= cp2 - szAttributes + 1;
if (m > 0)
_tcscpy(szAttributes, cp2+1);
else
szAttributes[0] = _T('\0');
m = _tcslen(szAttributes);
}
}
else
break;
}
///////////////////////////////////////////////////////////
else if (_tcsnicmp(szAttributes, _T("SIZE"), 4) == 0)
{
TCHAR *cp2 = _tcschr(szAttributes, _T('"'));
if (cp2)
{
m -= cp2 - szAttributes + 1;
_tcscpy(szAttributes, cp2+1);
cp2 = _tcschr(szAttributes, _T('"'));
if (cp2)
{
int nSize = _ttoi(szAttributes);
lf.lfHeight -= nSize;
nSizeChange = nSize;
m -= cp2 - szAttributes + 1;
if (m > 0)
_tcscpy(szAttributes, cp2+1);
else
szAttributes[0] = _T('\0');
m = _tcslen(szAttributes);
}
}
else
break;
}
else
{
while ((_tcslen(szAttributes) > 0) &&
(szAttributes[0] != _T(' ')))
{
m--;
_tcscpy(szAttributes, &szAttributes[1]);
}
}
}
}
else
{
TRACE(_T("ERROR no closing >\n"));
pszText += 5;
n -= 5;
}
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(pszText, _T("</FONT>"), 7) == 0) // check for </FONT>
{
n -= 7;
pszText += 7;
crTextNew = crText;
crBkgndNew = crBackground;
memcpy(&lf, &prev_lf, sizeof(lf));
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(pszText, _T("<A"), 2) == 0) // check for <A
{
TCHAR *cp = 0;
if ((cp = _tcsistr(pszText, _T("HREF="))) != NULL) // check for HREF=
{
cp += 5;
if (*cp == _T('"'))
cp += 1;
TCHAR *cp2 = _tcschr(cp, _T('>'));
if (cp2)
{
size_t len = cp2 - cp;
if (pXHDS->pszAnchor)
delete [] pXHDS->pszAnchor;
pXHDS->pszAnchor = new TCHAR [len+4];
memset(pXHDS->pszAnchor, 0, (len+4)*sizeof(TCHAR));
_tcsncpy(pXHDS->pszAnchor, cp, len);
size_t last = _tcslen(pXHDS->pszAnchor);
if (last > 0)
last--;
if (pXHDS->pszAnchor[last] == _T('"'))
pXHDS->pszAnchor[last] = _T('\0');
TRACE(_T("len=%d pXHDS->szUrl=<%s>\n"), len, pXHDS->pszAnchor);
n -= (int) (cp2 + 1 - pszText);
pszText = cp2 + 1;
TRACE(_T("pszText=<%s>\n"), pszText);
// set start X of url
pXHDS->rectAnchor.left = rectText.left + nXOffset;
TRACE(_T("setting pXHDS->rectAnchor.left to %d\n"), pXHDS->rectAnchor.left);
crTextNew = pXHDS->crAnchorText; //RGB(0,0,255); //pXHDS->crText;
crBkgndNew = crBackground;
memcpy(&lf, &prev_lf, sizeof(lf));
bInAnchor = TRUE;
if (bUnderlineUrl)
{
pXHDS->bAnchorIsUnderlined = TRUE;
bUnderline++;
}
}
}
else
{
TRACE(_T("ERROR no closing >\n"));
pszText += 2;
n -= 2;
}
continue;
}
///////////////////////////////////////////////////////////////////////
else if (_tcsnicmp(pszText, _T("</A>"), 4) == 0) // check for </A>
{
n -= 4;
pszText += 4;
if (bInAnchor)
{
pXHDS->rectAnchor.right = rectText.left + nXOffset;
pXHDS->bHasAnchor = TRUE;
TRACE(_T("setting pXHDS->rectAnchor.right to %d\n"), pXHDS->rectAnchor.right);
if (bUnderlineUrl)
bUnderline--;
crTextNew = crText;
crBkgndNew = crBackground;
memcpy(&lf, &prev_lf, sizeof(lf));
}
bInAnchor = FALSE;
continue;
}
///////////////////////////////////////////////////////////////////////
// plain text
else
{
TRACE(_T("text: pszText=<%s>\n"), pszText);
TCHAR *cp = _tcschr(pszText, _T('<'));
if (cp)
{
// there's another tag
_tcsncpy(pszText1, pszText, cp - pszText);
pszText1[cp-pszText] = _T('\0');
TRACE(_T("pszText1=<%s>\n"), pszText1);
if (_tcslen(pszText1) <= 0)
{
if (_tcslen(pszText) != 0)
{
_tcscpy(pszText1, pszText);
n -= 1;
}
}
pszText = cp;
}
else
{
// no more html tags
_tcscpy(pszText1, pszText);
pszText = NULL;
}
}
TRACE(_T("pszText=<%s>\n"), pszText);
TRACE(_T("pszText1=<%s>\n"), pszText1);
// create new font ------------------------------------------
lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL;
lf.lfUnderline = (BYTE) bUnderline;
lf.lfItalic = (BYTE) bItalic;
lf.lfStrikeOut = (BYTE) bStrikeThrough;
HFONT hNewFont = CreateFontIndirect(&lf);
_ASSERTE(hNewFont);
HFONT hOldFont = (HFONT) SelectObject(hMemDC, hNewFont);
SetTextColor(hMemDC, crTextNew);
if (pXHDS->crTextBackground != COLOR_NONE)
SetBkColor(hMemDC, pXHDS->crTextBackground);
else
SetBkMode(hMemDC, TRANSPARENT); // need transparency for italic fonts
// replace char entities ------------------------------------
size_t end = _tcslen(pszText1);
buflen = end + 100;
_ASSERTE(buf == NULL);
buf = new TCHAR [buflen];
memset(buf, 0, buflen*sizeof(TCHAR));
_tcsncpy(buf, pszText1, buflen-1);
ReplaceCharEntities(buf, end);
int len = (int)_tcslen(buf);
SIZE size;
GetTextExtentPoint32(hMemDC, buf, len, &size);
LONG width = size.cx;
if ((crBkgndNew != crBackground) &&
(pXHDS->crTextBackground == COLOR_NONE))
{
// changing backgrounds, so fill in with new color
HBRUSH hbrushnew = CreateSolidBrush(crBkgndNew);
if (hbrushnew)
{
RECT rect = rectText;
rect.right = rect.left + width + 1;
if (bItalic)
{
rect.right += 1; // italic needs a little more
if (!IsTrueType(hMemDC))
rect.right += 2; // non-TTF fonts need even more
}
if (rect.right > rectText.right)
rect.right = rectText.right;
FillRect(hMemDC, &rect, hbrushnew);
DeleteObject(hbrushnew);
}
}
UINT uFormat = pXHDS->uFormat;
if (pXHDS->bUseEllipsis)
uFormat |= DT_END_ELLIPSIS;
if (pXHDS->bHasAnchor)
{
// set rect for anchor
RECT rectCalc = rectText;
int nHeight = DrawText(hMemDC, buf, -1, &rectCalc, uFormat | DT_CALCRECT);
TRACE(_T("nHeight=%d -----\n"), nHeight);
pXHDS->rectAnchor.bottom = pXHDS->rectAnchor.top + nHeight;
}
RECT savedrect = rectText;
GetTextMetrics(hMemDC, &tm);
int nBaselineAdjust = tm.tmAscent / 2;
if (bSubscript)
{
rectText.top += nBaselineAdjust;
rectText.bottom += nBaselineAdjust;
}
if (bSuperscript)
{
rectText.top -= nBaselineAdjust;
rectText.bottom -= nBaselineAdjust;
}
// draw text ------------------------------------------------
TRACE(_T("DrawText: <%s>\n"), buf);
DrawText(hMemDC, buf, -1, &rectText, uFormat);
rectText = savedrect;
nSizeChange = 0;
if (hOldFont)
SelectObject(hMemDC, hOldFont);
if (hNewFont)
DeleteObject(hNewFont);
hNewFont = 0;
hOldFont = 0;
delete [] buf;
buf = NULL;
rectText.left += width;
n -= (int)_tcslen(pszText1);
} // while
// save the rightmost pixel position - note that rectText
// is remapped to 0,0 for the memory dc
pXHDS->nRightX = rectText.left + nXOffset;
TRACE(_T("nRightX = %d =====\n"), pXHDS->nRightX);
// end double buffering
BitBlt(hDC, rectDraw.left, rectDraw.top, nRectWidth, nRectHeight,
hMemDC, 0, 0, SRCCOPY);
// swap back the original bitmap
if (hOldBitmap)
SelectObject(hMemDC, hOldBitmap);
if (hBitmap)
DeleteObject(hBitmap);
hBitmap = 0;
DeleteDC(hMemDC);
hMemDC = 0;
if (pTextBuffer)
delete [] pTextBuffer;
pTextBuffer = 0;
if (pszText1)
delete [] pszText1;
pszText1 = 0;
bInDraw = FALSE;
return nWidth;
}
///////////////////////////////////////////////////////////////////////////////
// IsTrueType
BOOL CXHtmlDraw::IsTrueType(HDC hDC)
{
BOOL rc = FALSE;
_ASSERTE(hDC);
TEXTMETRIC tm;
if (hDC && GetTextMetrics(hDC, &tm))
rc = tm.tmPitchAndFamily & TMPF_TRUETYPE;
return rc;
}
///////////////////////////////////////////////////////////////////////////////
// InitCharEntities
void CXHtmlDraw::InitCharEntities()
{
for (int i = 0; m_aCharEntities[i].pszName != NULL; i++)
{
m_aCharEntities[i].cCode = (TCHAR) (i + 2); // don't use 0 or 1
}
}
///////////////////////////////////////////////////////////////////////////////
// ReplaceCharEntities
void CXHtmlDraw::ReplaceCharEntities(TCHAR * buf, size_t buflen)
{
_ASSERTE(buf);
if (buf)
{
if (_tcschr(buf, _T('\001')))
{
TCHAR *cp1 = buf;
TCHAR *cp2 = buf;
while (cp1 < (buf + buflen))
{
TCHAR c = *cp1++;
if (c == _T('\0'))
break;
if (c == _T('\001')) // is this a char entity?
{
// get next char - it is table index
c = *cp1++;
if (c == _T('\0'))
break;
c = GetCharEntity(c);
}
*cp2++ = c;
}
*cp2 = _T('\0');
}
}
}
///////////////////////////////////////////////////////////////////////////////
// GetCharEntity
TCHAR CXHtmlDraw::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;
}
///////////////////////////////////////////////////////////////////////////////
// GetPlainText
int CXHtmlDraw::GetPlainText(const TCHAR *html,
TCHAR *plain,
DWORD dwPlainSize)
{
size_t nSize = 0;
_ASSERTE(html);
if (html)
{
if (plain)
memset(plain, 0, dwPlainSize*sizeof(TCHAR));
if (_tcschr(html, _T('<')) || _tcschr(html, _T('&')))
{
// there is html in this string
// we are stripping out character entities, so the
// resulting string will be shorter than the original
size_t buflen = _tcslen(html) + 100;
TCHAR *buf1 = new TCHAR [buflen];
TCHAR *buf2 = new TCHAR [buflen];
memset(buf1, 0, buflen*sizeof(TCHAR));
memset(buf2, 0, buflen*sizeof(TCHAR));
_tcsncpy(buf1, html, buflen-1);
TCHAR ent[2] = { _T('\0') };
// loop to remove character entities
for (int i = 0; m_aCharEntities[i].pszName != NULL; i++)
{
ent[0] = m_aCharEntities[i].cSymbol;
int nRep = _tcsistrrep(buf1, m_aCharEntities[i].pszName, ent, buf2);
if (nRep > 0)
_tcscpy(buf1, buf2);
}
TRACE(_T("after entities: <%s>\n"), buf1);
TCHAR *cp1 = buf1;
TCHAR *cp2 = NULL;
nSize = _tcslen(buf1);
memset(buf2, 0, buflen*sizeof(TCHAR));
while (cp1 < (buf1 + nSize))
{
if (!*cp1)
break;
// look for html tag
cp2 = _tcschr(cp1, _T('<'));
if (cp2)
{
// copy everything up to this point
_tcsncat(buf2, cp1, cp2-cp1);
cp1 = cp2 + 1; // in case no >
cp2 = _tcschr(cp1, _T('>'));
if (cp2)
cp1 = cp2 + 1;
}
else
{
// no more tags, just copy rest
_tcscat(buf2, cp1);
break;
}
}
TRACE(_T("GetPlainText: buf1=<%s>\n"), buf1);
TRACE(_T("GetPlainText: buf2=<%s>\n"), buf2);
if (plain)
{
_tcsncpy(plain, buf2, dwPlainSize-1);
TRACE(_T("GetPlainText: plain=<%s>\n"), plain);
nSize = _tcslen(plain);
}
else
{
// no output buffer, just return required size
nSize = _tcslen(buf2);
}
delete [] buf1;
delete [] buf2;
}
else
{
// no html in string, just copy to output buffer
if (plain)
{
_tcsncpy(plain, html, dwPlainSize-1);
nSize = _tcslen(plain);
}
else
{
// no output buffer, just return required size
nSize = _tcslen(html);
}
}
}
return (int)nSize;
}
///////////////////////////////////////////////////////////////////////////////
// IsOverAnchor
BOOL CXHtmlDraw::IsOverAnchor(HWND hWnd, XHTMLDRAWSTRUCT * pXHDS)
{
TRACE(_T("in CXHtmlDraw::IsOverAnchor\n"));
BOOL rc = FALSE;
if (pXHDS && pXHDS->bHasAnchor && hWnd && ::IsWindow(hWnd))
{
POINT point;
GetCursorPos(&point);
::ScreenToClient(hWnd, &point);
RECT rect = pXHDS->rectAnchor;
//TRACERECT(rect);
//TRACEPOINT(point);
rc = ::PtInRect(&rect, point);
if (rc)
{
TRACE(_T("mouse over anchor\n"));
}
}
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -