Introduction
Microsoft VC++ 6.0 can only build a RichEdit 1.0 app with MFC 4.2. My friends always ask me how to use RichEdit 2.0 or another version of the RichEdit control in a VC6 project. So, this tiny article is just a little attempt of mine to share the info with all of you, and it may be helpful. :)
This article will show you how to use RichEdit v4.1 (RICHEDIT50W
in msftedit.dll) directly.
An additional advantage of the method which is shown in the article is that we can get a fully functional CRichEditView
based on the RichEdit v4.1 control, instead of just creating a RichEdit v4.1 control with only text functions. Because we still use MFC, we just only replace the base RichEdit control from 1.0 to 4.1. So, we can still Ctrl+V a bitmap from the clipboard to our CRichEditView
, can still insert an object and add some hyperlink text with the in-place MFC member functions.
Background
Since Windows(R) has upgraded to Version 6.1, why should we only use RichEdit 1.0 or 2.0? Well... here is something that could let you use RichEdit 4.1 (msftedit.dll) directly.
Principle
Because our CMyAppView
is derived from CRichEditView
, we can see the statements below in VIEWRICH.CPP:
CRichEditView::CRichEditView():
CCtrlView(_T("RICHEDIT"), AFX_WS_DEFAULT_VIEW |
WS_HSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL |
ES_MULTILINE | ES_NOHIDESEL | ES_SAVESEL | ES_SELECTIONBAR)
{
m_bSyncCharFormat = m_bSyncParaFormat = TRUE;
m_lpRichEditOle = NULL;
...
}
Let's go deeper. The MFC source shows us that CRichEditView
is derived from CCtrlView
, and in VIEWCORE.CPP, in the constructor of CCtrlView
, we can see CCtrlView
save the class name "RICHEDIT
" which gets from CRichEditView
into m_strClass
, then use this member var
in the PreCreateWindow()
and Create()
functions. The code is shown below:
CCtrlView::CCtrlView(LPCTSTR lpszClass, DWORD dwStyle)
{
m_strClass = lpszClass;
m_dwDefaultStyle = dwStyle;
}
BOOL CCtrlView::PreCreateWindow(CREATESTRUCT& cs)
{
ASSERT(cs.lpszClass == NULL);
cs.lpszClass = m_strClass;CREATESTRUCT here
...
return CView::PreCreateWindow(cs);
}
As we know, every window is created by the CreateWindowEx()
API eventually. 'CREATESTRUCT& cs
' is just brought from CWnd::CreateEx()
, which is used to tell the system how to create a window.
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{
CREATESTRUCT cs;
cs.dwExStyle = dwExStyle;
cs.lpszClass = lpszClassName;
cs.lpszName = lpszWindowName;
cs.style = dwStyle;
cs.x = x;
cs.y = y;
cs.cx = nWidth;
cs.cy = nHeight;
cs.hwndParent = hWndParent;
cs.hMenu = nIDorHMenu;
cs.hInstance = AfxGetInstanceHandle();
cs.lpCreateParams = lpParam;
if (!PreCreateWindow(cs)) {
PostNcDestroy();
return FALSE;
}
AfxHookWindowCreate(this);
HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
...
}
How Do We Use the Code?
This is a very typical project produced by the MFC App Wiz. CMyAppView
is the View Class derived from CRichEditView
.
class CMyAppView : public CRichEditView
{
...
}
There are two steps. First, put 'm_strClass=TEXT("RichEdit50W");
' into the the constructor of CMyAppView
. It should look like this:
CMyAppView::CMyAppView()
{
m_strClass=TEXT("RichEdit50W");
...
}
Then , put 'LoadLibrary(TEXT("msftedit.dll"));
' into the constructor of the CMyApp
class. And, OLE must be initialized too. When it is done, it should look like this:
CMyApp::CMyApp()
{
CoInitialize(NULL);
m_hinstRE41=LoadLibrary(TEXT("msftedit.dll"));
...
}
CMyApp::~CMyApp()
{
if(m_hinstRE41)
FreeLibrary(m_hinstRE41);
}
CMyApp::InitInstance()
{
AfxOleInit(); AfxEnableControlContainer(); ...
}
Another Important Tip
In CMyAppView::OnDestroy
, you should see:
void CGreatTracerView::OnDestroy()
{
COleClientItem* pActiveItem = GetDocument()->
GetInPlaceActiveItem(this); if (pActiveItem != NULL && pActiveItem->GetActiveView() == this)
{
pActiveItem->Deactivate();
ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
}
CRichEditView::OnDestroy();
}
By the way, I really recommend building the project in Unicode. :)
History
- 2010.2.6: First version - 1.0.
- 2010.2.7: Version 1.1 - Added more intro and the principle part.
- 2010.2.23: Version 1.2 - Corrected the version error; msftedit.dll contains RichEdit v4.1 (the class name is
RICHEDIT50W
), not v5.0.