void CHTRichEditCtrl::AddLine(LPCTSTR pszMsg, int iLen, bool bLink, COLORREF cr, COLORREF bk, DWORD mask)
{
	int iMsgLen = (iLen == -1) ? _tcslen(pszMsg) : iLen;
	if (iMsgLen == 0)
		return;

	// Get Edit contents dimensions and cursor position
	long lStartChar, lEndChar;
	GetSel(lStartChar, lEndChar);
	int iSize = GetWindowTextLength();

	// Get Auto-AutoScroll state depending on scrollbar position
	bool bAutoAutoScroll = m_bAutoScroll;
	// Use the 'ScrollInfo' only, if there is a scrollbar available, otherwise we would
	// use a scrollinfo which points to the top and we would thus stay at the top.
	bool bScrollInfo = false;
	SCROLLINFO si;
	si.cbSize = sizeof si;
	si.fMask = SIF_ALL;
	if ((GetStyle() & WS_VSCROLL) && GetScrollInfo(SB_VERT, &si)) {
		bScrollInfo = true;
		// use some threshold to determine if at end or "very near" at end, unfortunately
		// this is needed to get around richedit specific stuff. this threshold (pixels)
		// should somewhat reflect the font size used in the control.
		bAutoAutoScroll = (si.nPos >= (int)(si.nMax - si.nPage - 20));
	}

	// Reduce flicker by ignoring WM_PAINT
	m_bNoPaint = true;
	BOOL bIsVisible = IsWindowVisible();
	if (bIsVisible)
		SetRedraw(FALSE);

	// Remember where we are
	//int iFirstLine = !bAutoAutoScroll ? GetFirstVisibleLine() : 0;
	POINT ptScrollPos;
	SendMessage(EM_GETSCROLLPOS, 0, (LPARAM)&ptScrollPos);
	
	// Select at the end of text and replace the selection
	SafeAddLine(iSize, pszMsg, iMsgLen, lStartChar, lEndChar, bLink, cr, bk, mask);
	SetSel(lStartChar, lEndChar); // Restore previous selection

	if (bAutoAutoScroll)
		ScrollToLastLine();
	else {
		//LineScroll(iFirstLine - GetFirstVisibleLine());
		SendMessage(EM_SETSCROLLPOS, 0, (LPARAM)&ptScrollPos);
	}

	m_bNoPaint = false;
	if (bIsVisible) {
		SetRedraw();
		Invalidate();
	}
}
void CHTRichEditCtrl::OnSize(UINT nType, int cx, int cy)
{
	// Use the 'ScrollInfo' only, if there is a scrollbar available, otherwise we would
	// use a scrollinfo which points to the top and we would thus stay at the top.
	bool bAtEndOfScroll;
	SCROLLINFO si;
	si.cbSize = sizeof si;
	si.fMask = SIF_ALL;
	if ((GetStyle() & WS_VSCROLL) && GetScrollInfo(SB_VERT, &si))
		bAtEndOfScroll = (si.nPos >= (int)(si.nMax - si.nPage));
	else
		bAtEndOfScroll = true;

	CRichEditCtrl::OnSize(nType, cx, cy);

	if (bAtEndOfScroll)
		ScrollToLastLine();
}
void CHTRichEditCtrl::AddLine(LPCTSTR pszMsg, int iLen, bool bLink, COLORREF cr, COLORREF bk, DWORD mask)
{
	int iMsgLen = (iLen == -1) ? _tcslen(pszMsg) : iLen;
	if (iMsgLen == 0)
		return;
#ifdef _DEBUG
	//	if (pszMsg[iMsgLen - 1] == _T('\n'))
	//		ASSERT( iMsgLen >= 2 && pszMsg[iMsgLen - 2] == _T('\r') );
#endif

	// Get Edit contents dimensions and cursor position
	long lStartChar, lEndChar;
	GetSel(lStartChar, lEndChar);
	int iSize = GetWindowTextLength();

	if (lStartChar == iSize && iSize == lEndChar)
	{
		// The cursor resides at the end of text
		SCROLLINFO si;
		si.cbSize = sizeof si;
		si.fMask = SIF_ALL;
		if (m_bAutoScroll && GetScrollInfo(SB_VERT, &si) && si.nPos >= (int)(si.nMax - si.nPage + 1))
		{
			// Not scrolled away
			SafeAddLine(iSize, pszMsg, iLen, lStartChar, lEndChar, bLink, cr, bk, mask);
			if (m_bAutoScroll && !IsWindowVisible())
				ScrollToLastLine();
		}
		else
		{
			// Reduce flicker by ignoring WM_PAINT
			m_bNoPaint = true;
			BOOL bIsVisible = IsWindowVisible();
			if (bIsVisible)
				SetRedraw(FALSE);

			// Remember where we are
			int iFirstLine = !m_bAutoScroll ? GetFirstVisibleLine() : 0;

			// Select at the end of text and replace the selection
			// This is a very fast way to add text to an edit control
			SafeAddLine(iSize, pszMsg, iLen, lStartChar, lEndChar, bLink, cr, bk, mask);
			//if (m_bAutoScroll && lStartChar == lEndChar)
			//	lStartChar = lEndChar = -1;
			SetSel(lStartChar, lEndChar); // Restore our previous selection

			if (!m_bAutoScroll)
				LineScroll(iFirstLine - GetFirstVisibleLine());
			else
				ScrollToLastLine();

			m_bNoPaint = false;
			if (bIsVisible){
				SetRedraw();
				if (m_bRichEdit)
					Invalidate();
			}
		}
	}
	else
	{
		// We should add the text anyway...

		// Reduce flicker by ignoring WM_PAINT
		m_bNoPaint = true;
		BOOL bIsVisible = IsWindowVisible();
		if (bIsVisible)
			SetRedraw(FALSE);

		// Remember where we are
		int iFirstLine = !m_bAutoScroll ? GetFirstVisibleLine() : 0;
		// Very annoying problems with EM_GETSCROLLPOS/EM_SETSCROLLPOS. Depending
		// on the amount of data in the control, the control may start to scroll up
		// by itself(!!) -- obviously because of some internal rounding errors..
		//
		// Using 'LineScroll' also gives glitches (also depending on the amount of
		// data stored in the control), but at least it doesn't start to show some 'life'
		/*POINT ptScrollPos;
		if (!m_bAutoScroll)
			SendMessage(EM_GETSCROLLPOS, 0, (LPARAM)&ptScrollPos);*/

		if (lStartChar != lEndChar)
		{
			// If we are currently selecting some text, we have to find out
			// if the caret is near the beginning of this block or near the end.
			// Note that this does not always work. Because of the EM_CHARFROMPOS
			// message returning only 16 bits this will fail if the user has selected
			// a block with a length dividable by 64k.

			// NOTE: This may cause a lot of terrible CRASHES within the RichEdit control when used for a RichEdit control!?
			// To reproduce the crash: click in the RE control while it's drawing a line and start a selection!
			if (!m_bRichEdit){
				CPoint pt;
				::GetCaretPos(&pt);
				int iCaretPos = CharFromPos(pt);
				if (abs((lStartChar % 0xffff - iCaretPos)) < abs((lEndChar % 0xffff - iCaretPos)))
				{
					iCaretPos = lStartChar;
					lStartChar = lEndChar;
					lEndChar = iCaretPos;
				}
			}
		}

		// Note: This will flicker, if someone has a good idea how to prevent this - let me know

		// Select at the end of text and replace the selection
		// This is a very fast way to add text to an edit control
		SafeAddLine(iSize, pszMsg, iLen, lStartChar, lEndChar, bLink, cr, bk, mask);
		//if (m_bAutoScroll && lStartChar == lEndChar)
		//	lStartChar = lEndChar = -1;
		SetSel(lStartChar, lEndChar); // Restore our previous selection

		if (!m_bAutoScroll){
			LineScroll(iFirstLine - GetFirstVisibleLine());
			//SendMessage(EM_SETSCROLLPOS, 0, (LPARAM)&ptScrollPos);
		}
		else
			ScrollToLastLine();

		m_bNoPaint = false;
		if (bIsVisible){
			SetRedraw();
			if (m_bRichEdit)
				Invalidate();
		}
	}
}
void CHTRichEditCtrl::ApplySkin()
{
	if (!m_strSkinKey.IsEmpty())
	{
		// Use the 'ScrollInfo' only, if there is a scrollbar available, otherwise we would
		// use a scrollinfo which points to the top and we would thus stay at the top.
		bool bAtEndOfScroll;
		SCROLLINFO si;
		si.cbSize = sizeof si;
		si.fMask = SIF_ALL;
		if ((GetStyle() & WS_VSCROLL) && GetScrollInfo(SB_VERT, &si))
			bAtEndOfScroll = (si.nPos >= (int)(si.nMax - si.nPage));
		else
			bAtEndOfScroll = true;

		COLORREF cr;
		if (theApp.LoadSkinColor(m_strSkinKey + _T("Fg"), cr)) {
			m_bDfltForeground = false;
			m_crForeground = cr;
		}
		else {
			m_bDfltForeground = m_crDfltForeground == CLR_DEFAULT;
			m_crForeground = m_bDfltForeground ? GetSysColor(COLOR_WINDOWTEXT) : m_crDfltForeground;
		}

		bool bSetCharFormat = false;
		CHARFORMAT cf;
		GetDefaultCharFormat(cf);
		if (!m_bDfltForeground && (cf.dwEffects & CFE_AUTOCOLOR)) {
			cf.dwEffects &= ~CFE_AUTOCOLOR;
			bSetCharFormat = true;
		}
		else if (m_bDfltForeground && !(cf.dwEffects & CFE_AUTOCOLOR)) {
			cf.dwEffects |= CFE_AUTOCOLOR;
			bSetCharFormat = true;
		}
		if (bSetCharFormat) {
			cf.dwMask |= CFM_COLOR;
			cf.crTextColor = m_crForeground;
			VERIFY( SetDefaultCharFormat(cf) );
			VERIFY( GetSelectionCharFormat(m_cfDefault) );
		}

		if (theApp.LoadSkinColor(m_strSkinKey + _T("Bk"), cr)) {
			m_bDfltBackground = false;
			m_crBackground = cr;
			SetBackgroundColor(FALSE, m_crBackground);
		}
		else {
			m_bDfltBackground = m_crDfltBackground == CLR_DEFAULT;
			m_crBackground = m_bDfltBackground ? GetSysColor(COLOR_WINDOW) : m_crDfltBackground;
			SetBackgroundColor(m_bDfltBackground, m_crBackground);
		}

		if (bAtEndOfScroll)
			ScrollToLastLine();
	}
	else
	{
		m_bDfltForeground = m_crDfltForeground == CLR_DEFAULT;
		m_crForeground = m_bDfltForeground ? GetSysColor(COLOR_WINDOWTEXT) : m_crDfltForeground;

		m_bDfltBackground = m_crDfltBackground == CLR_DEFAULT;
		m_crBackground = m_bDfltBackground ? GetSysColor(COLOR_WINDOW) : m_crDfltBackground;

		VERIFY( GetSelectionCharFormat(m_cfDefault) );
	}
	PurgeSmileyCaches();
}
void CHTRichEditCtrl::SetFont(CFont* pFont, BOOL bRedraw)
{
	// Use the 'ScrollInfo' only, if there is a scrollbar available, otherwise we would
	// use a scrollinfo which points to the top and we would thus stay at the top.
	bool bAtEndOfScroll;
	SCROLLINFO si;
	si.cbSize = sizeof si;
	si.fMask = SIF_ALL;
	if ((GetStyle() & WS_VSCROLL) && GetScrollInfo(SB_VERT, &si))
		bAtEndOfScroll = (si.nPos >= (int)(si.nMax - si.nPage));
	else
		bAtEndOfScroll = true;

	LOGFONT lf = {0};
	pFont->GetLogFont(&lf);

	CHARFORMAT cf = {0};
	cf.cbSize = sizeof cf;

	cf.dwMask |= CFM_BOLD;
	cf.dwEffects |= (lf.lfWeight == FW_BOLD) ? CFE_BOLD : 0;

	cf.dwMask |= CFM_ITALIC;
	cf.dwEffects |= (lf.lfItalic) ? CFE_ITALIC : 0;

	cf.dwMask |= CFM_UNDERLINE;
	cf.dwEffects |= (lf.lfUnderline) ? CFE_UNDERLINE : 0;

	cf.dwMask |= CFM_STRIKEOUT;
	cf.dwEffects |= (lf.lfStrikeOut) ? CFE_STRIKEOUT : 0;

	cf.dwMask |= CFM_SIZE;
	HDC hDC = ::GetDC(HWND_DESKTOP);
	int iPointSize = -MulDiv(lf.lfHeight, 72, GetDeviceCaps(hDC, LOGPIXELSY));
	cf.yHeight = iPointSize * 20;
	::ReleaseDC(NULL, hDC);

	cf.dwMask |= CFM_FACE;
	cf.bPitchAndFamily = lf.lfPitchAndFamily;
	_tcsncpy(cf.szFaceName, lf.lfFaceName, _countof(cf.szFaceName));
	cf.szFaceName[_countof(cf.szFaceName) - 1] = _T('\0');

	// although this should work correctly (according SDK) it may give false results (e.g. the "click here..." text
	// which is shown in the server info window may not be entirely used as a hyperlink???)
	//	cf.dwMask |= CFM_CHARSET;
	//	cf.bCharSet = lf.lfCharSet;

	cf.yOffset = 0;
	VERIFY( SetDefaultCharFormat(cf) );

	// copy everything except the color
	m_cfDefault.dwMask = (cf.dwMask & ~CFM_COLOR) | (m_cfDefault.dwMask & CFM_COLOR);
	m_cfDefault.dwEffects = cf.dwEffects;
	m_cfDefault.yHeight = cf.yHeight;
	m_cfDefault.yOffset = cf.yOffset;
	//m_cfDefault.crTextColor = cf.crTextColor;
	m_cfDefault.bCharSet = cf.bCharSet;
	m_cfDefault.bPitchAndFamily = cf.bPitchAndFamily;
	memcpy(m_cfDefault.szFaceName, cf.szFaceName, sizeof(m_cfDefault.szFaceName));

	PurgeSmileyCaches();

	if (bAtEndOfScroll)
		ScrollToLastLine();

	if (bRedraw)
	{
		Invalidate();
		UpdateWindow();
	}
}
示例#6
0
//////////////////////////////////////////////////////////////////////////////
// This function is based on Daniel Lohmann's article "CEditLog - fast logging
// into an edit control with cout" at http://www.codeproject.com
void CLogEditCtrl::AddLine(LPCTSTR pszMsg, int iLen)
{
	int iMsgLen = (iLen == -1) ? _tcslen(pszMsg) : iLen;
	if (iMsgLen == 0)
		return;
#ifdef _DEBUG
	if (pszMsg[iMsgLen - 1] == _T('\n'))
		ASSERT( iMsgLen >= 2 && pszMsg[iMsgLen - 2] == _T('\r') );
#endif

	// Get Edit contents dimensions and cursor position
	int iStartChar, iEndChar;
	GetSel(iStartChar, iEndChar);
	int iWndTxtLen = GetWindowTextLength();

	if (iStartChar == iWndTxtLen && iWndTxtLen == iEndChar)
	{
		// The cursor resides at the end of text
		SCROLLINFO si;
		si.cbSize = sizeof si;
		si.fMask = SIF_ALL;
		if (m_bAutoScroll && GetScrollInfo(SB_VERT, &si) && si.nPos >= (int)(si.nMax - si.nPage + 1))
		{
			// Not scrolled away
			SafeAddLine(iWndTxtLen, iMsgLen, pszMsg, iStartChar, iEndChar);
			if (m_bAutoScroll && !IsWindowVisible())
				ScrollToLastLine();
		}
		else
		{
			// Reduce flicker by ignoring WM_PAINT
			m_bNoPaint = true;
			BOOL bIsVisible = IsWindowVisible();
			if (bIsVisible)
				SetRedraw(FALSE);

			// Remember where we are
			int nFirstLine = !m_bAutoScroll ? GetFirstVisibleLine() : 0;
		
			// Select at the end of text and replace the selection
			// This is a very fast way to add text to an edit control
			SafeAddLine(iWndTxtLen, iMsgLen, pszMsg, iStartChar, iEndChar);
			SetSel(iStartChar, iEndChar, TRUE); // Restore our previous selection

			if (!m_bAutoScroll)
				LineScroll(nFirstLine - GetFirstVisibleLine());
			else
				ScrollToLastLine();

			m_bNoPaint = false;
			if (bIsVisible){
				SetRedraw();
				if (m_bRichEdit)
					Invalidate();
			}
		}
	}
	else
	{
		// We should add the text anyway...

		// Reduce flicker by ignoring WM_PAINT
		m_bNoPaint = true;
		BOOL bIsVisible = IsWindowVisible();
		if (bIsVisible)
			SetRedraw(FALSE);

		// Remember where we are
		int nFirstLine = !m_bAutoScroll ? GetFirstVisibleLine() : 0;
	
		if (iStartChar != iEndChar)
		{
			// If we are currently selecting some text, we have to find out
			// if the caret is near the beginning of this block or near the end.
			// Note that this does not always work. Because of the EM_CHARFROMPOS
			// message returning only 16 bits this will fail if the user has selected 
			// a block with a length dividable by 64k.

			// NOTE: This may cause a lot of terrible CRASHES within the RichEdit control when used for a RichEdit control!?
			// To reproduce the crash: click in the RE control while it's drawing a line an start a selection!
			if (!m_bRichEdit){
			    CPoint pt;
			    ::GetCaretPos(&pt);
			    int nCaretPos = CharFromPos(pt);
			    if (abs((iStartChar % 0xffff - nCaretPos)) < abs((iEndChar % 0xffff - nCaretPos)))
			    {
				    nCaretPos = iStartChar;
				    iStartChar = iEndChar;
				    iEndChar = nCaretPos;
			    }
		    }
		}

		// Note: This will flicker, if someone has a good idea how to prevent this - let me know
		
		// Select at the end of text and replace the selection
		// This is a very fast way to add text to an edit control
		SafeAddLine(iWndTxtLen, iMsgLen, pszMsg, iStartChar, iEndChar);
		SetSel(iStartChar, iEndChar, TRUE); // Restore our previous selection

		if (!m_bAutoScroll)
			LineScroll(nFirstLine - GetFirstVisibleLine());
		else
			ScrollToLastLine();

		m_bNoPaint = false;
		if (bIsVisible){
			SetRedraw();
			if (m_bRichEdit)
				Invalidate();
		}
	}
}