📄 hypertextctrl.cpp
字号:
if(si.nMax != si.nMin)
m_iVertPos = si.nPos * 100 / (si.nMax - si.nMin);
SetScrollInfo(SB_VERT, &si);
UpdateVisLines();
InvalidateRect(NULL,FALSE);
return TRUE;
}
void CHyperTextCtrl::OnMouseMove(UINT nFlags,CPoint pt){
CRect rcClient;
GetClientRect(rcClient);
if(PtInRect(rcClient, pt) && m_iLineHeight)
{
bool bFound = false;
uint16 i = pt.y / m_iLineHeight;
if(i < m_VisLines.size())
{
std::vector<CVisLine>::iterator it = m_VisLines.begin() + i;
for(CVisLine::iterator jt = it->begin(); jt != it->end(); jt++)
if(pt.x >= jt->m_rcBounds.left && pt.x <= jt->m_rcBounds.right)
{
if(jt->m_pHyperLink != NULL)
{
HighlightLink(&*jt, pt);
bFound = true;
if (GetCapture() != this)
SetCapture();
}
break;
}
}
if(!bFound){
RestoreLink();
if (GetCapture() == this)
ReleaseCapture();
}
}
else
ReleaseCapture();
}
void CHyperTextCtrl::OnLButtonDown(UINT nFlags,CPoint pt){
CRect rcClient;
GetClientRect(rcClient);
if(PtInRect(rcClient, pt) && m_iLineHeight)
{
bool bFound = false;
uint16 i = pt.y / m_iLineHeight;
if(i < m_VisLines.size()){
std::vector<CVisLine>::iterator it = m_VisLines.begin() + i;
for(CVisLine::iterator jt = it->begin(); jt != it->end(); jt++)
if(pt.x >= jt->m_rcBounds.left && pt.x <= jt->m_rcBounds.right)
{
if(jt->m_pHyperLink != NULL)
{
jt->m_pHyperLink->Execute();
bFound = true;
}
break;
}
}
}
//m_tip.OnLButtonDown(nFlags,pt);
}
BOOL CHyperTextCtrl::OnMouseWheel(UINT nFlags,short zDelta,CPoint pt){
CRect rc;
GetWindowRect(rc);
if(PtInRect(rc, pt))
{
int iScrollLines;
SystemParametersInfo(SPI_GETWHEELSCROLLLINES,
0,
&iScrollLines,
0);
m_iWheelDelta -= zDelta;
if(abs(m_iWheelDelta) >= WHEEL_DELTA)
{
if(m_iWheelDelta > 0)
{
for(int i = 0; i<iScrollLines; i++)
PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);
}
else
{
for(int i = 0; i<iScrollLines; i++)
PostMessage(WM_VSCROLL, SB_LINEUP, 0);
}
m_iWheelDelta %= WHEEL_DELTA;
}
}
return true;
//m_tip.OnMouseWheel(nFlags,zDelta,pt);
}
LRESULT CHyperTextCtrl::OnCaptureChanged(WPARAM wParam, LPARAM lParam){
RestoreLink();
return 0;
}
BOOL CHyperTextCtrl::OnEraseBkgnd(CDC* pDC){
return TRUE;
}
// Operations
CPreparedHyperText* CHyperTextCtrl::GetHyperText(){
return m_Text;
}
void CHyperTextCtrl::SetHyperText(CPreparedHyperText* Src, bool bInvalidate){
if (Src)
m_Text = Src;
else
m_Text = &standart_Text;
UpdateSize(bInvalidate);
}
void CHyperTextCtrl::AppendText(const CString& sText, bool bInvalidate){
m_Text->AppendText(sText);
UpdateSize(bInvalidate);
}
void CHyperTextCtrl::AppendHyperLink(const CString& sText, const CString& sTitle, const CString& sCommand, const CString& sDirectory, bool bInvalidate){
m_Text->AppendHyperLink(sText, sTitle, sCommand, sDirectory);
UpdateSize(bInvalidate);
}
void CHyperTextCtrl::AppendKeyWord(const CString& sText, COLORREF icolor){
m_Text->AppendKeyWord(sText,icolor);
UpdateSize(true);
}
void CHyperTextCtrl::AppendHyperLink(const CString& sText, const CString& sTitle, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool bInvalidate){
m_Text->AppendHyperLink(sText, sTitle, hWnd, uMsg, wParam, lParam);
UpdateSize(bInvalidate);
}
void CHyperTextCtrl::SetLinkColor(COLORREF LinkColor, bool bInvalidate){
m_LinkColor = LinkColor;
if(bInvalidate)
InvalidateRect(NULL,FALSE);
}
void CHyperTextCtrl::UpdateSize(bool bRepaint){
if(m_bDontUpdateSizeInfo)
return;
m_bDontUpdateSizeInfo = true;
DWORD dwStyle = GetWindowLongPtr(m_hWnd,GWL_STYLE);
bool vscrollneeded = false;
CClientDC dc(this);
CFont* hOldFont = dc.SelectObject(m_Font);
int iScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
m_Lines.clear();
CRect rc;
GetClientRect(rc);
rc.DeflateRect(2,0);
m_iMaxWidth = 0;
m_iLinesHeight = 0;
long iMaxWidthChars = 0;
SIZE sz;
if(rc.Width() > 5 && rc.Height() > 5)
{
std::list<CHyperLink>::iterator it = m_Text->GetLinks().begin();
std::list<CKeyWord>::iterator ht = m_Text->GetKeywords().begin();
LPCTSTR s = m_Text->GetText();
int len = m_Text->GetText().GetLength();
int width = rc.Width();
int npos, // new position
pos = 0, // current position
ll, // line length
rll; // line length with wordwrap (if used)
while(len>0)
{
ll = len;
npos = ll;
for(int i = 0; i < len; i++)
{
if(s[i] == _T('\r') || s[i] == _T('\n'))
{
if(s[i] == _T('\r') && ((i+1) < len) && s[i+1] == _T('\n'))
npos = i + 2;
else
npos = i + 1;
ll = i;
break;
}
}
if(!::GetTextExtentExPoint(dc, s , (ll > 512) ? 512 : ll, width, &rll, NULL, &sz) || sz.cy == 0)
{
::GetTextExtentExPoint(dc, _T(" ") , 1, 0, NULL, NULL, &sz);
sz.cx = 0;
rll = ll;
}
if(rll>ll)
rll = ll;
if(!check_bits(dwStyle, HTC_WORDWRAP))
rll = ll;
else
if(rll < ll)
npos = rll;
if(rll>0)
{
if((rll < len) && !_istspace((_TUCHAR)s[rll]))
for(int i = rll - 1; i >= 0; i--)
if(_istspace((_TUCHAR)s[i]))
{
rll = i;
npos = i + 1;
break;
}
}
if(npos == 0)
npos = 1;
CLineInfo li(pos, pos + rll - 1);
CLinePartInfo pl(pos, pos + rll - 1);
while(it != m_Text->GetLinks().end() && it->End() < pos)
it++;
while(ht != m_Text->GetKeywords().end() && ht->End() < pos)
ht++;
//split the line into parts of hypertext, normaltext, keywords etc
for (int i = pl.Begin(); i < pl.End(); i++){
if (it != m_Text->GetLinks().end() && i >= it->Begin() && it->End() > i){ // i_a
if (i > pl.m_xBegin){
CLinePartInfo pln(pl.m_xBegin,i-1);
li.push_back(pln);
}
if (it->End() > pl.End()){
pl.m_xBegin = pl.End() + 1;
CLinePartInfo pln(i, pl.End(), &*it);
li.push_back(pln);
break;
}
else{
pl.m_xBegin = it->End() + 1;
CLinePartInfo pln(i, it->End(), &*it);
li.push_back(pln);
i = pl.m_xBegin;
it++;
}
}
else if (ht != m_Text->GetKeywords().end() && i >= ht->Begin() && ht->End() > i){ // i_a
if (i > pl.m_xBegin){
CLinePartInfo pln(pl.m_xBegin,i-1);
li.push_back(pln);
}
if (ht->End() > pl.End()){
pl.m_xBegin = pl.End() + 1;
CLinePartInfo pln(i, pl.End(),0, &*ht);
li.push_back(pln);
break;
}
else{
pl.m_xBegin = ht->End() + 1;
CLinePartInfo pln(i, ht->End(),0, &*ht);
li.push_back(pln);
i = pl.m_xBegin;
ht++;
}
}
}
if(pl.Len()>0)
li.push_back(pl);
m_iLineHeight = sz.cy;
m_iLinesHeight+=m_iLineHeight;
if(sz.cx > m_iMaxWidth)
m_iMaxWidth = sz.cx;
if(iMaxWidthChars < li.Len())
iMaxWidthChars = li.Len();
m_Lines.push_back(li);
pos+=npos;
s+=npos;
len-=npos;
if((m_iLinesHeight + iScrollHeight) > rc.Height()){
vscrollneeded = true;
}
}
if(bRepaint)
InvalidateRect(rc);
}
dc.SelectObject(hOldFont);
// Update scroll bars
dwStyle = GetWindowLongPtr(m_hWnd,GWL_STYLE);
if (check_bits(dwStyle, HTC_AUTO_SCROLL_BARS)){
if (vscrollneeded){
if (!vscrollon)
ShowScrollBar(SB_VERT,TRUE);
dwStyle|=WS_VSCROLL;
vscrollon = true;
}
else if (!vscrollneeded){
ShowScrollBar(SB_VERT,FALSE);
vscrollon = false;
}
}
if(check_bits(dwStyle, HTC_AUTO_SCROLL_BARS) && !check_bits(dwStyle, HTC_WORDWRAP))
{
if(m_iMaxWidth > rc.Width())
{
ShowScrollBar(SB_HORZ,TRUE);
dwStyle|=WS_HSCROLL;
};
}
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
if(check_bits(dwStyle,WS_HSCROLL) && m_iMaxWidth != 0)
{
si.nMin = 0;
si.nMax = iMaxWidthChars + iMaxWidthChars/2;
si.nPos = (int)(double(si.nMax) * m_iHorzPos / 100);
si.nPage = (rc.Width() * si.nMax)/m_iMaxWidth;
SetScrollInfo(SB_HORZ, &si, FALSE);
}
if(check_bits(dwStyle,WS_VSCROLL) && m_iLinesHeight != 0)
{
si.nMin = 0;
si.nMax = (int)m_Lines.size();
si.nPos = si.nMax;//(int)(double(si.nMax) * m_iVertPos / 100);
si.nPage = (rc.Height() * si.nMax)/m_iLinesHeight;
SetScrollInfo(SB_VERT, &si, TRUE);
}
m_bDontUpdateSizeInfo = false;
UpdateVisLines();
}
void CHyperTextCtrl::UpdateFonts(){
DWORD dwStyle = GetWindowLongPtr(m_hWnd,GWL_STYLE);
m_LinksFont.DeleteObject();
m_HoverFont.DeleteObject();
LOGFONT lf;
m_Font->GetLogFont(&lf);
if(check_bits(dwStyle, HTC_UNDERLINE_LINKS))
lf.lfUnderline = TRUE;
m_LinksFont.CreateFontIndirect(&lf);
m_Font->GetLogFont(&lf);
if(check_bits(dwStyle, HTC_UNDERLINE_HOVER))
lf.lfUnderline = TRUE;
m_HoverFont.CreateFontIndirect(&lf);
}
void CHyperTextCtrl::UpdateVisLines(){
RestoreLink();
DWORD dwStyle = ::GetWindowLongPtr(m_hWnd,GWL_STYLE);
int id = 1;
if(check_bits(dwStyle, HTC_ENABLE_TOOLTIPS))
{
for(std::vector<CVisLine>::iterator itv = m_VisLines.begin(); itv != m_VisLines.end(); itv++)
for(CVisLine::iterator jt = itv->begin(); jt != itv->end(); jt++)
{
if(jt->m_pHyperLink != NULL)
m_tip.DelTool(this, id++);
}
}
m_VisLines.clear();
std::vector<CLineInfo>::iterator it = m_Lines.begin();
int iVertPos = 0;
int iHorzPos = 0;
if(check_bits(dwStyle,WS_VSCROLL))
iVertPos = GetScrollPos(SB_VERT);
if(check_bits(dwStyle,WS_HSCROLL))
iHorzPos = GetScrollPos(SB_HORZ);
if(iVertPos >= (int)m_Lines.size())
return;
it+=iVertPos;
CClientDC dc(this); // device context for painting
CFont* hOldFont = dc.SelectObject(m_Font);
int ypos = 0;
LPCTSTR s = m_Text->GetText();
CRect rcClient;
GetClientRect(rcClient);
for(; it != m_Lines.end(); it++)
{
uint16 XPos = 2;
uint16 LinePos = it->Begin();
uint16 Offset = 0;
uint16 Len = 0;
CVisLine vl;
CRect rcBounds;
std::vector<CLinePartInfo>::iterator jt;
for(jt = it->begin(); jt != it->end(); jt++)
{
if(jt->Begin() <= (LinePos + iHorzPos) && jt->End() >= (LinePos + iHorzPos))
{
Offset = LinePos + iHorzPos;
Len = jt->Len() - ((LinePos + iHorzPos) - jt->Begin());
break;
}
}
while(jt != it->end())
{
if(Len > 0)
{
SIZE sz;
::GetTextExtentExPoint(dc, s + Offset, Len, 0, NULL, NULL, &sz);
rcBounds.left = XPos;
XPos+=sz.cx;
rcBounds.right = XPos;
rcBounds.top = ypos;
rcBounds.bottom = ypos+m_iLineHeight;
vl.push_back(CVisPart(*jt, rcBounds, Offset, Len, NULL, NULL));
}
if(XPos > rcClient.Width())
break;
jt++;
if (jt == it->end())
break;
Offset = jt->m_xBegin;
Len = jt->Len();
}
m_VisLines.push_back(vl);
ypos+=m_iLineHeight;
if(ypos>rcClient.bottom)
break;
}
CVisPart *pPrev = NULL, *pNext;
id = 1;
for(std::vector<CVisLine>::iterator it2 = m_VisLines.begin(); it2 != m_VisLines.end(); it2++)
for(CVisLine::iterator jt = it2->begin(); jt != it2->end(); jt++)
{
pNext = &*jt;
if(pPrev != NULL &&
pPrev->m_pHyperLink != NULL &&
pPrev->m_pHyperLink == pNext->m_pHyperLink &&
pPrev != pNext)
{
pPrev->m_pNext = pNext;
pNext->m_pPrev = pPrev;
}
pPrev = pNext;
if(check_bits(dwStyle, HTC_ENABLE_TOOLTIPS) && jt->m_pHyperLink != NULL)
m_tip.AddTool(this, (LPCTSTR)jt->m_pHyperLink->Title(), jt->m_rcBounds, id++);
}
dc.SelectObject(hOldFont);
}
void CHyperTextCtrl::HighlightLink(CVisPart* Part, const CPoint& MouseCoords){
if(m_pActivePart == Part)
return;
if(m_pActivePart != Part && m_pActivePart != NULL && Part != NULL && m_pActivePart->m_pHyperLink != Part->m_pHyperLink)
RestoreLink();
m_pActivePart = Part;
while(m_pActivePart->m_pPrev != NULL)
m_pActivePart = m_pActivePart->m_pPrev;
CClientDC dc(this);
CFont* hOldFont = dc.SelectObject(&m_HoverFont);
dc.SetBkColor(m_BkColor);
dc.SetTextColor(m_HoverColor);
LPCTSTR s = m_Text->GetText();
CVisPart* p = m_pActivePart;
while(p != NULL)
{
TextOut(dc, p->m_rcBounds.left, p->m_rcBounds.top,
s + p->m_iRealBegin, p->m_iRealLen);
p = p->m_pNext;
}
dc.SelectObject(hOldFont);
SetCursor(m_LinkCursor);
}
void CHyperTextCtrl::RestoreLink(){
if(m_pActivePart == NULL)
return;
CClientDC dc(this);
CFont* hOldFont = dc.SelectObject(&m_LinksFont);
dc.SetBkColor(m_BkColor);
dc.SetTextColor(m_LinkColor);
LPCTSTR s = m_Text->GetText();
CVisPart* p = m_pActivePart;
while(p != NULL)
{
TextOut(dc, p->m_rcBounds.left, p->m_rcBounds.top,
s + p->m_iRealBegin, p->m_iRealLen);
p = p->m_pNext;
}
dc.SelectObject(hOldFont);
m_pActivePart = NULL;
SetCursor(m_DefaultCursor);
}
void CHyperTextCtrl::OnSysColorChange() {
//adjust colors
CWnd::OnSysColorChange();
SetColors();
}
void CHyperTextCtrl::SetColors() {
m_BkColor = GetSysColor(COLOR_WINDOW);
m_TextColor = GetSysColor(COLOR_WINDOWTEXT);
//perhaps some sort of check against the bk and text color can be made
//before blindly using these default link colors?
m_LinkColor = RGB(0,0,255);
m_HoverColor = RGB(255,0,0);
}
void CHyperTextCtrl::LoadHandCursor() {
CString windir;
GetWindowsDirectory(windir.GetBuffer(MAX_PATH), MAX_PATH);
windir.ReleaseBuffer();
windir += _T("\\winhlp32.exe");
HMODULE hModule = LoadLibrary(windir);
ASSERT( m_LinkCursor == NULL );
if (hModule){
HCURSOR hTempCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
if (hTempCursor){
m_LinkCursor = CopyCursor(hTempCursor);
VERIFY( DestroyCursor(hTempCursor) );
}
FreeLibrary(hModule);
}
if (m_LinkCursor == NULL){
//this shouldn't happen... but just in case
m_LinkCursor = LoadCursor(NULL,IDC_ARROW);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -