www.pudn.com > RichTextEx.rar > RichEditCtrlEx.cpp


//****************************************************************************** 
//****************************************************************************** 
// Owner:   Andrew Forget (AndrewFo,x3438)  
//          Copyright ?1999, SOFTIMAGE, Avid Technologies 
//------------------------------------------------------------------------------ 
// 
// @doc     RICHEDITCTRLEX 
// 
// @module  RichEditCtrlEx.cpp | 
//          This file implements the rich edit control extended class 
//          . 
// 
// @version 
//------------------------------------------------------------------------------ 
//.Version: Date:       Author:     Comments: 
//.-------- ----------- ----------- -------------------------------------------- 
//.  1.0    01/18/99    AndrewFo    New file. 
//****************************************************************************** 
//****************************************************************************** 
 
 
//****************************************************************************** 
// 
// Includes 
// 
//****************************************************************************** 
 
#include "StdAfx.h" 
 
#include "RichEditCtrlEx.h" 
#include ".\richeditctrlex.h" 
#include "afxctl.h" 
 
 
//****************************************************************************** 
// 
// Debugging 
// 
//****************************************************************************** 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
//****************************************************************************** 
// Owner:   Andrew Forget (AndrewFo,x3438)  
//------------------------------------------------------------------------------ 
// 
// @mfunc   | _AFX_RICHEDITEX_STATE | _AFX_RICHEDITEX_STATE | 
//          Constructor for . 
// 
// @syntax  _AFX_RICHEDITEX_STATE() ; 
// 
// @version 
//------------------------------------------------------------------------------ 
//.Version: Date:       Author:     Comments: 
//.-------- ----------- ----------- -------------------------------------------- 
//.  1.0    01/18/99    AndrewFo    New code. 
//****************************************************************************** 
 
_AFX_RICHEDITEX_STATE::_AFX_RICHEDITEX_STATE() 
{ 
	m_hInstRichEdit20 = NULL ; 
 
} 
 
//****************************************************************************** 
// Owner:   Andrew Forget (AndrewFo,x3438)  
//------------------------------------------------------------------------------ 
// 
// @mfunc   | _AFX_RICHEDITEX_STATE | ~_AFX_RICHEDITEX_STATE | 
//          Destructor for . 
// 
// @syntax  ~_AFX_RICHEDITEX_STATE() ; 
// 
// @version 
//------------------------------------------------------------------------------ 
//.Version: Date:       Author:     Comments: 
//.-------- ----------- ----------- -------------------------------------------- 
//.  1.0    01/18/99    AndrewFo    New code. 
//****************************************************************************** 
 
_AFX_RICHEDITEX_STATE::~_AFX_RICHEDITEX_STATE() 
{ 
	if( m_hInstRichEdit20 != NULL ) 
	{ 
		::FreeLibrary( m_hInstRichEdit20 ) ; 
	} 
} 
 
 
//****************************************************************************** 
// 
// Global Data 
// 
//****************************************************************************** 
 
_AFX_RICHEDITEX_STATE _afxRichEditStateEx ; 
 
 
//****************************************************************************** 
// Owner:   Andrew Forget (AndrewFo,x3438)  
//------------------------------------------------------------------------------ 
// 
// @func    BOOL PASCAL | AfxInitRichEditEx | 
//          This function must be called prior to creating any dialog which 
//          uses the version 2.0 rich edit control.  For created classes, this 
//          is called automatically. 
// 
// @syntax  BOOL PASCAL AfxInitRichEditEx() ; 
// 
// @rdesc   BOOL : A boolean value indicating: 
// @flag        TRUE  | Success. 
// @flag        FALSE | Failure. 
// 
// @comm    NOTE: This function will not work if AfxInitRichEdit() has been 
//          called first and this will clash with the use of the CRichEditCtrl 
//          class (including the CRichEditView class). 
// 
// @version 
//------------------------------------------------------------------------------ 
//.Version: Date:       Author:     Comments: 
//.-------- ----------- ----------- -------------------------------------------- 
//.  1.0    01/18/99    AndrewFo    New code. 
//****************************************************************************** 
 
BOOL PASCAL AfxInitRichEditEx() 
{ 
	if( ! ::AfxInitRichEdit() ) 
	{ 
		return FALSE ; 
	} 
 
	_AFX_RICHEDITEX_STATE* l_pState = &_afxRichEditStateEx ; 
 
	if( l_pState->m_hInstRichEdit20 == NULL ) 
	{ 
		l_pState->m_hInstRichEdit20 = LoadLibraryA( "RICHED20.DLL" ) ; 
	} 
 
	return l_pState->m_hInstRichEdit20 != NULL ; 
} 
 
 
 
//****************************************************************************** 
// Owner:   Andrew Forget (AndrewFo,x3438)  
//------------------------------------------------------------------------------ 
// 
// @mfunc   | CRichEditCtrlEx | CRichEditCtrlEx | 
//          Constructor for . 
// 
// @syntax  CRichEditCtrlEx() ; 
// 
// @version 
//------------------------------------------------------------------------------ 
//.Version: Date:       Author:     Comments: 
//.-------- ----------- ----------- -------------------------------------------- 
//.  1.0    01/18/99    AndrewFo    New code. 
//****************************************************************************** 
 
CRichEditCtrlEx::CRichEditCtrlEx() 
{ 
		m_hCursor = NULL; 
} 
 
//****************************************************************************** 
// Owner:   Andrew Forget (AndrewFo,x3438)  
//------------------------------------------------------------------------------ 
// 
// @mfunc   | CRichEditCtrlEx | ~CRichEditCtrlEx | 
//          Destructor for . 
// 
// @syntax  ~CRichEditCtrlEx() ; 
// 
// @version 
//------------------------------------------------------------------------------ 
//.Version: Date:       Author:     Comments: 
//.-------- ----------- ----------- -------------------------------------------- 
//.  1.0    01/18/99    AndrewFo    New code. 
//****************************************************************************** 
 
CRichEditCtrlEx::~CRichEditCtrlEx() 
{ 
} 
 
 
//****************************************************************************** 
// Owner:   Andrew Forget (AndrewFo,x3438)  
//------------------------------------------------------------------------------ 
// 
// @msgmap  CRichEditCtrl | CRichEditCtrlEx | 
//          Message map for . 
// 
// @version 
//------------------------------------------------------------------------------ 
//.Version: Date:       Author:     Comments: 
//.-------- ----------- ----------- -------------------------------------------- 
//.  1.0    01/18/99    AndrewFo    New code. 
//****************************************************************************** 
 
BEGIN_MESSAGE_MAP( CRichEditCtrlEx, CRichEditCtrl ) 
 
	//{{AFX_MSG_MAP( CRichEditCtrlEx ) 
	ON_WM_CREATE() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_MOUSEMOVE() 
	ON_WM_SETCURSOR() 
	//}}AFX_MSG_MAP 
	ON_NOTIFY_REFLECT(EN_LINK, OnLink) 
END_MESSAGE_MAP() 
 
 
//****************************************************************************** 
// Owner:   Andrew Forget (AndrewFo,x3438)  
//------------------------------------------------------------------------------ 
// 
// @mfunc   BOOL | CRichEditCtrlEx | Create | 
//          This method is used to create the version 2.0 rich edit control. 
// 
// @syntax  BOOL Create( 
//          			DWORD		in_dwStyle,  
//          			const RECT& in_rcRect,  
//          			CWnd*		in_pParentWnd,  
//          			UINT		in_nID ) ; 
// 
// @parm    DWORD | in_dwStyle | 
//          The styles for the rich edit control. 
// 
// @parm    const RECT& | in_rcRect | 
//          The rectangle for the control window. 
// 
// @parm    CWnd* | in_pParentWnd | 
//          Pointer to the parent window. 
// 
// @parm    UINT | in_nID | 
//          The dialog control ID for the control. 
// 
// @rdesc   BOOL : A boolean value indicating: 
// @flag        TRUE  | Sucess. 
// @flag        FALSE | Failure. 
// 
// @version 
//------------------------------------------------------------------------------ 
//.Version: Date:       Author:     Comments: 
//.-------- ----------- ----------- -------------------------------------------- 
//.  1.0    01/18/99    AndrewFo    New code. 
//****************************************************************************** 
 
BOOL CRichEditCtrlEx::Create( 
			DWORD		in_dwStyle,  
			const RECT& in_rcRect,  
			CWnd*		in_pParentWnd,  
			UINT		in_nID ) 
{ 
	if( ! ::AfxInitRichEditEx() ) 
	{ 
		return FALSE ; 
	} 
 
	CWnd* l_pWnd = this ; 
 
	return l_pWnd->Create( _T( "RichEdit20A" ), NULL, in_dwStyle, in_rcRect, in_pParentWnd, in_nID ) ; 
} 
void CRichEditCtrlEx::OnLink(NMHDR *pNMHDR, LRESULT *result) 
{ 
	ENLINK *link = (ENLINK *) pNMHDR; 
 
	*result = 0; 
 
	if (link->msg == WM_LBUTTONDOWN) { 
		CHARRANGE cr; 
		GetSel(cr); 
		SetSel(link->chrg); 
		CString url = GetSelText(); 
		SetSel(cr); 
 
		ShellExecute(NULL, _T("open"), url, NULL,NULL, SW_SHOW); 
 
		*result = 1; 
	} 
} 
 
void CRichEditCtrlEx::AppendMsg(TCHAR chMsg[]) 
{ 
//	BOOL b = (GetStyle() & ES_READONLY); 
//	SetReadOnly(FALSE); 
 
	SetSel(-1, -1); 
//	CHARRANGE cr; 
//	GetSel(cr); 
	CHARFORMAT defFormat; 
	defFormat.cbSize = sizeof(defFormat); 
	defFormat.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_FACE | CFM_SIZE | CFM_COLOR; 
	GetDefaultCharFormat(defFormat); 
 
 
	CHARFORMAT cf; 
	cf.cbSize = sizeof(cf); 
	cf = defFormat; 
	cf.crTextColor = RGB(0,0,255); 
	cf.dwEffects = 0; 
	//SetSel(cr.cpMin, -1); 
	SetSelectionCharFormat(cf); 
 
/* 
		PARAFORMAT pf; 
		pf.cbSize = sizeof(pf); 
		pf.dwMask = PFM_STARTINDENT; 
		pf.dxStartIndent = 200; 
		SetParaFormat(pf);*/ 
	 
	 
	CString strText; 
	strText.Format("%s", chMsg); 
	ReplaceSel(strText); 
 
 
 
//	SetSel(-1, -1); 
	HideSelection(FALSE, TRUE); 
	SendMessage(EM_SCROLLCARET, 0, 0); 
	SetSelectionCharFormat(defFormat); 
//	ReplaceSel("\r\n\r\n"); 
//	ScrollToBottom(); 
//	ReplaceSel("\r\n"); 
	//ScrollToBottom(); 
} 
 
void CRichEditCtrlEx::InsertMsg(TCHAR chMsg[], COLORREF color) 
{ 
	long start, end; 
	SetSel(-1, -1); 
 
	GetSel(start, end); 
 
	CHARFORMAT defFormat; 
	defFormat.cbSize = sizeof(defFormat); 
	defFormat.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_FACE | CFM_SIZE | CFM_COLOR; 
	GetDefaultCharFormat(defFormat); 
 
	PARAFORMAT pf; 
	pf.cbSize = sizeof(pf); 
	pf.dwMask = PFM_STARTINDENT; 
	pf.dxStartIndent = 0; 
	SetParaFormat(pf); 
 
 
	CHARFORMAT cf; 
	cf.cbSize = sizeof(cf); 
 
	CString strText; 
	strText.Format("%s", chMsg); 
 
	ReplaceSel(strText); 
	SetSel(start, -1); 
	cf = defFormat; 
	cf.crTextColor = color; 
	cf.dwEffects = 0; 
	cf.dwEffects |= CFM_BOLD; 
	SetSelectionCharFormat(cf); 
	SetSel(-1, -1); 
	ReplaceSel("\r\n"); 
	 
//	GetDefaultCharFormat(cf); 
 
 
//	SetSel(-1, -1); 
//	ReplaceSel(start); 
} 
 
void CRichEditCtrlEx::ScrollToBottom(void) 
{ 
	// get the current end of the window 
	CPoint point = GetCharPos(GetTextLength()); 
	CRect rect; 
	GetClientRect(&rect); 
 
	// scroll the bottom into view 
	while (point.y > rect.bottom) { 
		LineScroll(1); 
		point = GetCharPos(GetTextLength()); 
	} 
} 
 
void CRichEditCtrlEx::Clear(void) 
{ 
	SetWindowText(_T("")); 
} 
 
int CRichEditCtrlEx::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CRichEditCtrl ::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	// TODO: Add your specialized creation code here 
	m_iMaxWidth = 0; 
	m_iLinesHeight = 0; 
	m_bDontUpdateSizeInfo = false; 
	m_iHorzPos = 0; 
	m_iVertPos = 0; 
/* 
		m_DefaultFont.CreatePointFont(100,_T("Times New Roman")); 
		m_Font = m_DefaultFont;*/ 
	 
	m_LinkColor = RGB(0,0,255); 
	m_HoverColor = RGB(255,0,0); 
	m_BkColor = GetSysColor(COLOR_WINDOW); 
	m_TextColor = GetSysColor(COLOR_WINDOWTEXT); 
	m_LinkCursor = LoadCursor(NULL,IDC_ARROW); 
	m_DefaultCursor = LoadCursor(NULL,IDC_ARROW); 
	m_pActivePart = NULL; 
	m_iWheelDelta = 0; 
	 
	// create a tool tip 
	m_tip.Create((CWnd*)this); 
/* 
		ASSERT(m_tip.IsWindow()); 
		if(m_tip.IsWindow())*/ 
	m_tip.Activate(TRUE); 
	 
//	UpdateFonts(); 
	return 0; 
} 
 
 
 
void CRichEditCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	 
	CRichEditCtrl ::OnLButtonDown(nFlags, point); 
 
	CRect rcClient; 
	GetClientRect(rcClient); 
	if(PtInRect(rcClient, point)) 
	{ 
		std::list m_Links = m_Text.GetLinks(); 
		std::list::iterator it; 
		for (it = m_Links.begin(); it != m_Links.end(); it++) 
		{ 
			CHyperLink hl = *it; 
			hl.End(); 
			TRACE("CRichEditCtrlEx::OnLButtonDown HyperLink begin pos is:%d, end pos is:%d\n", hl.Begin(), hl.End()); 
			CPoint pt1 = GetCharPos(hl.Begin()); 
			CPoint pt2 = GetCharPos(hl.End()); 
			TRACE("Link Text Begin x:%d\n", pt1.x); 
			TRACE("Link Text End x:%d\n", pt2.x); 
			TRACE("CRichEditCtrlEx::OnLButtonDown Cur Point x:%d\n", point.x); 
			if (pt1.x < point.x && point.x< pt2.x ) 
			{ 
				TRACE("Mouse Down Over link text!!!!\n"); 
				hl.Execute(); 
				break; 
			} 
		} 
	} 
} 
 
void CRichEditCtrlEx::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	 
	CRichEditCtrl ::OnMouseMove(nFlags, point); 
 
	CRect rcClient; 
	GetClientRect(rcClient); 
	if(PtInRect(rcClient, point)) 
	{ 
/* 
					if(GetCapture() != m_hWnd) 
						SetCapture();*/ 
			 
		std::list m_Links = m_Text.GetLinks(); 
		std::list::iterator it; 
		for (it = m_Links.begin(); it != m_Links.end(); it++) 
		{ 
			CHyperLink hl = *it; 
			hl.End(); 
			TRACE("HyperLink begin pos is:%d, end pos is:%d\n", hl.Begin(), hl.End()); 
			CPoint pt1 = GetCharPos(hl.Begin()); 
			CPoint pt2 = GetCharPos(hl.End()); 
			TRACE("Link Text Begin x:%d,y:%d\n", pt1.x, pt1.y); 
			TRACE("Link Text End x:%d,y:%d\n", pt2.x, pt2.y); 
			TRACE("Cur Point x:%d,y:%d\n", point.x, point.y); 
			if (pt1.x < point.x && point.x< pt2.x) 
			{ 
				 
					TRACE("Mouse over link text!\n"); 
					if (m_hCursor == NULL) 
						SetDefaultCursor(); 
					if (m_hCursor != NULL) 
						::SetCursor(m_hCursor); 
			 
					break; 
			} 
		} 
/* 
				int n = this->CharCharFromPos(point); 
				TRACE("CRichEditCtrlEx::OnMouseMove:%d", n);*/ 
	} 
 
} 
void CRichEditCtrlEx::RestoreLink() 
{ 
/* 
		if(m_pActivePart == NULL) 
			return; 
		 
		CClientDC dc(this); 
	//	CFontHandle hOldFont = dc.SelectFont(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.SelectFont(hOldFont); 
		 
		m_pActivePart = NULL; 
		SetCursor(m_DefaultCursor);*/ 
	 
} 
void CRichEditCtrlEx::HighlightLink(CVisPart* Part, const CPoint& MouseCoords) 
{ 
	 
} 
void CRichEditCtrlEx::SetDefaultCursor() 
{ 
	if (m_hCursor == NULL)                // No cursor handle - load our own 
	{ 
		// Get the windows directory 
		CString strWndDir; 
		GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH); 
		strWndDir.ReleaseBuffer(); 
		 
		strWndDir += _T("\\winhlp32.exe"); 
		// This retrieves cursor #106 from winhlp32.exe, which is a hand pointer 
		HMODULE hModule = LoadLibrary(strWndDir); 
		if (hModule != NULL) 
		{ 
			HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106)); 
			if (hHandCursor != NULL) 
				m_hCursor = CopyCursor(hHandCursor); 
		} 
		FreeLibrary(hModule); 
	} 
} 
 
BOOL CRichEditCtrlEx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)  
{ 
	// TODO: Add your message handler code here and/or call default 
	if (m_hCursor == NULL) 
		SetDefaultCursor(); 
 //   if (m_hCursor != NULL) 
//		::SetCursor(m_hCursor); 
  //  return TRUE; 
	return CRichEditCtrl ::OnSetCursor(pWnd, nHitTest, message); 
}