CRichEditCtrlEx : Replacing “RICHEDIT” control with “RichEdit20A”

While writing a dev notes Visual Studio plug in, I wanted the rich edit control in a
dialog to understand URL’s so developers could add links to sites and email addresses.
  After talking to "Long John", he led me to the easy way of doing it, and
now I am posting the work for others.  Basically this requires CRichEditCtrlEx to use
the new rich edit DLL RICHED20.DLL.  The first thing to do it change the window class
name of the rich edit controls from "RICHEDIT" to "RichEdit20A" in the
*.rc file.  Next, we create a class derived from CRichEditCtrl called CRichEditCtrlEx
and override the Create() method:

class CRichEditCtrlEx : public CRichEditCtrl
{
public:
CRichEditCtrlEx();
virtual ~CRichEditCtrlEx();

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL( CRichEditCtrlEx )
public:
virtual BOOL Create( DWORD in_dwStyle, const RECT& in_rcRect,
CWnd* in_pParentWnd, UINT in_nID );
//}}AFX_VIRTUAL

// Generated message map functions
protected:
//{{AFX_MSG( CRichEditCtrlEx )
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

Now implement the Create() method like this:

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 );
}

This is almost exactly what is in CRichEditCtrl::Create(), except the different window
class name, and the call to AfxInitRichEdit() has been changed to AfxInitRichEditEx()
which first calls AfxInitRichEdit (we do not want to break the normal CRichEditCtrl).
  In the RichEditCtrlEx.h file, you need to add the DLL holder class and function
prototype:

class _AFX_RICHEDITEX_STATE
{
public:
_AFX_RICHEDITEX_STATE();
virtual ~_AFX_RICHEDITEX_STATE();

HINSTANCE m_hInstRichEdit20 ;
};

BOOL PASCAL AfxInitRichEditEx();

Now, in the source code, add the implementation:

_AFX_RICHEDITEX_STATE::_AFX_RICHEDITEX_STATE()
{
m_hInstRichEdit20 = NULL ;
}

_AFX_RICHEDITEX_STATE::~_AFX_RICHEDITEX_STATE()
{
if( m_hInstRichEdit20 != NULL )
{
::FreeLibrary( m_hInstRichEdit20 ) ;
}
}

_AFX_RICHEDITEX_STATE _afxRichEditStateEx ;

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 ;
}

Last thing to help out it we add a method to set the auto URL detection in the Rich
Edit to on/off:

inline BOOL CRichEditCtrlEx::AutoURLDetect( BOOL in_fEnable )
{
    ASSERT(::IsWindow( m_hWnd ) );
    return ( BOOL )::SendMessage( m_hWnd, EM_AUTOURLDETECT, in_fEnable, 0 );
}

See the attached sample for the full source code.

Now to use this in your code, you need to use CRichEditCtrlEx for the rich edits you
want to include URL detection, and you must call AfxInitRichEditEx() in your
CMyApp::InitInstance() if you have dialogs using the rich edit controls.

To then use the URL, you must set the event mask on the rich edit control to include
ENM_LINK and then the control will send EN_LINK notifications.  The EN_LINK
notification uses the ENLINK structure which includes a message ID.  This message
will be:

  • WM_LBUTTONDBLCLK
  • WM_LBUTTONDOWN
  • WM_LBUTTONUP
  • WM_MOUSEMOVE
  • WM_RBUTTONDBLCLK
  • WM_RBUTTONDOWN
  • WM_RBUTTONUP
  • WM_SETCURSOR

If you want to override the default action, set the pResult to 1, otherwise set it to
zero.  See the example code to see how to handle this notification.

Download demo project - 16KB (this sample was compiled
and tested using VC 6.0 sp1 on NT 4.0 sp4)

More by Author

Must Read