Пример #1
0
//-----------------------------------------------------------------------------
//  AppendToLogAndScroll()
///
/// \brief	Add a string to the serial log window at the current position,
///			then scroll to the end of the text such that the last line of
///			the text is shown at the bottom of the CRichEditCtrl.
///
/// The string is added to the message log starting at the current position,
/// i.e. without starting a new line. Then the control scrolls down to show
/// as much text as possible, including the last line of text at the very
/// bottom.
/// The string is displayed in the specified text color.
/// The string may be a multiline string using carriage return/line feed
/// (i.e. newline) characters to indicate a line breaks.
///
/// \param [in]		str		The string to add to the message log.
/// \param [in]		color	The text color of the string. You may use the
///							RGB(r,g,b) macro to specify the color byte-wise.
/// \return					An integer indicating sucess or failure:
///							- 0, if the function succeeded.
///							- (-1), if the function failed.
///							(This function always returns 0, because no
///							parameter or failure checking is done.)
///
/// \remark
/// The automatic scrolling function would be easy, if the MFC documentation
/// was correct. Unfortunetely, it is not as trivial as one might think.
/// If the CRichEditCtrl has the focus, it scrolls automatically if you
/// insert text programatically. If it does not have the focus, it does not
/// scroll automatically, so in that case you can use the LineScroll()
/// method and you get the results you would expect when reading the MFC docs.
/// This is true even if ES_AUTOxSCROLL style is NOT set.
///
/// So the point is to check in the AppendToLogAndScroll() method if the
/// affected CRichEditCtrl has the focus. If so, we must not call
/// LineScroll(). If not, it is safe to call LineSroll() to first scroll to
/// the very end, which means that the last line of text is shown at the top
/// of the CRichEditCtrl.
/// Then we call LineScroll() a second time, this time scrolling back by
/// the number of visible lines. This leads to having the last line of the
/// text being displayed at the bottom of CRichEditCtrl.
///
/// Please note that in this sample application, the CRichEditCtrl never has
/// the focus, because we always have to click a button in order to insert
/// text. However, if you are using the code in an application not based on
/// a dialog and that fills up the control where the user could have set focus
/// to the control first, this method would fail to scroll correctly without
/// checking the focus.
/// I used this code in an MDI application, and there the control claims
/// to have the focus if I click into the control before clicking a menu
/// command (whatever the reason might be why in that case the focus is
/// not lost to the menu command).
///
/// Please note that the code is written for maximum comprehension / good
/// readability, not for code or execution efficiency.
//-----------------------------------------------------------------------------
int CThreadTestDlg::AppendToLogAndScroll( CString str, COLORREF color )
{
    long nVisible = 0;
    long nInsertionPoint = 0;
    CHARFORMAT cf;

    // Initialize character format structure
    cf.cbSize = sizeof( CHARFORMAT );
    cf.dwMask = CFM_COLOR | CFM_SIZE;
    cf.dwEffects = 0; // To disable CFE_AUTOCOLOR
    cf.yHeight = 210;  // 1twips = 15px, 近似使用五号字体
    cf.crTextColor = color;

    // Set insertion point to end of text
    nInsertionPoint = m_ctrlLog.GetWindowTextLength();
    m_ctrlLog.SetSel( nInsertionPoint, -1 );

    // Set the character format
    m_ctrlLog.SetSelectionCharFormat( cf );

    // Replace selection. Because we have nothing
    // selected, this will simply insert
    // the string at the current caret position.
    m_ctrlLog.ReplaceSel( str );

    // Get number of currently visible lines or maximum number of visible lines
    // (We must call GetNumVisibleLines() before the first call to LineScroll()!)
    nVisible   = GetNumVisibleLines( &m_ctrlLog );

    // Now this is the fix of CRichEditCtrl's abnormal behaviour when used
    // in an application not based on dialogs. Checking the focus prevents
    // us from scrolling when the CRichEditCtrl does so automatically,
    // even though ES_AUTOxSCROLL style is NOT set.
    if ( &m_ctrlLog != m_ctrlLog.GetFocus() )
    {
        m_ctrlLog.LineScroll( INT_MAX );
        m_ctrlLog.LineScroll( 1 - nVisible );
    }

    return 0;
}
Пример #2
0
void CLogPid::DisplayData (LPCTSTR pszData)
{
	long nVisible = 0;
	
	if (m_bPause)
		return;

	// Format the selection as default text
	CHARFORMAT cf;
	cf.cbSize = sizeof(cf);
	cf.dwMask = CFM_COLOR;

	m_ctrlLog.GetSelectionCharFormat(cf);
	cf.dwEffects |= CFE_AUTOCOLOR;
	cf.yHeight = 183;
	strcpy( cf.szFaceName, FONT_NAME );
	m_ctrlLog.SetSelectionCharFormat(cf);

	// Add the event to the edit control
	m_ctrlLog.SetSel(-1,-1);
	m_ctrlLog.ReplaceSel(pszData);

	// Get number of currently visible lines or maximum number of visible lines
	// (We must call GetNumVisibleLines() before the first call to LineScroll()!)
	nVisible   = GetNumVisibleLines(&m_ctrlLog);

	// Now this is the fix of CRichEditCtrl's abnormal behaviour when used
	// in an application not based on dialogs. Checking the focus prevents
	// us from scrolling when the CRichEditCtrl does so automatically,
	// even though ES_AUTOxSCROLL style is NOT set.
	if (&m_ctrlLog != m_ctrlLog.GetFocus())
	{
		m_ctrlLog.LineScroll(INT_MAX);
		m_ctrlLog.LineScroll(1 - nVisible);
	}
}