⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hypertextctrl.cpp

📁 电驴的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	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 + -