65.9K
CodeProject 正在变化。 阅读更多。
Home

在 VC6 和其他 VS 版本中使用富文本编辑控件 5.0 的一种非常简单的方法

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.93/5 (8投票s)

2010年2月8日

CPOL

2分钟阅读

viewsIcon

63477

一个关于使用富文本编辑控件 5.0 的好技巧。

引言

Microsoft VC++ 6.0 只能构建使用 MFC 4.2 的富文本编辑控件 1.0 应用程序。我的朋友们总是问我如何在 VC6 项目中使用富文本编辑控件 2.0 或其他版本的富文本编辑控件。因此,这篇文章只是我尝试与大家分享信息的一点努力,可能对大家有所帮助。:)

本文将向您展示如何**直接**使用富文本编辑控件 v4.1(在 msftedit.dll 中为 RICHEDIT50W)。

文章中所示方法的另一个优点是,我们可以获得基于富文本编辑控件 v4.1 的功能齐全的 CRichEditView,而不仅仅是创建一个只包含**文本**功能的富文本编辑控件 v4.1。因为我们仍然使用 MFC,我们只是将基础富文本编辑控件从 1.0 替换为 4.1。因此,我们仍然可以从剪贴板 Ctrl+V 一个位图到我们的 CRichEditView,仍然可以插入一个对象并使用 MFC 成员函数添加一些超链接文本。

背景

既然 Windows(R) 已经升级到版本 6.1,为什么我们只使用富文本编辑控件 1.0 或 2.0 呢?嗯……这里有一些可以让您**直接**使用富文本编辑控件 4.1(msftedit.dll)的方法。

原理

因为我们的 CMyAppView 是从 CRichEditView 派生的,所以我们可以在 VIEWRICH.CPP 中看到以下语句

CRichEditView::CRichEditView():
  CCtrlView(_T("RICHEDIT"),      //MFC hard-coded the ClassName ....
                               //here is the Key.
                               //Our goal is to REPLACE "RICHEDIT"
                               //to "RichEdit50W". And we can do this in our
                               //View Class' Constructor. You can get those
                               //codes under this segment :)
    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;
     ...
    }

让我们深入了解一下。MFC 源代码告诉我们,CRichEditView 是从 CCtrlView 派生的,在 VIEWCORE.CPP 中,在 CCtrlView 的构造函数中,我们可以看到 CCtrlView 将类名“RICHEDIT”从 CRichEditView 保存到 m_strClass 中,然后在 PreCreateWindow()Create() 函数中使用这个成员 var。代码如下所示

CCtrlView::CCtrlView(LPCTSTR lpszClass, DWORD dwStyle)
{
 m_strClass = lpszClass;
 //here, MFC save the ClassName given by
 //CRichEditView's Constructor

 m_dwDefaultStyle = dwStyle;
}
BOOL CCtrlView::PreCreateWindow(CREATESTRUCT& cs)
{
 ASSERT(cs.lpszClass == NULL);
 cs.lpszClass = m_strClass;//CCtrlView apply the ClassName to a
CREATESTRUCT here
 ...
 return CView::PreCreateWindow(cs);
}

如我们所知,每个窗口最终都是由 CreateWindowEx() API 创建的。'CREATESTRUCT& cs' 只是从 CWnd::CreateEx() 传递过来的,用于告诉系统如何创建一个窗口。

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)
{
 // allow modification of several common create parameters
 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))//CCtrlView::PreCreateWindow() will be called here,
       //and our New ClassName "RichEdit50W" has been already in 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);
   // Our RichEdit v4.1(RICHEDIT50W) Ctrl
   // has been created successfully!
 ...
}

如何使用这段代码?

这是一个由 MFC App Wiz 生成的非常典型的项目。CMyAppView 是从 CRichEditView 派生的视图类。

class CMyAppView : public CRichEditView
{
...
}

有两步。首先,将 'm_strClass=TEXT("RichEdit50W");' 放入 CMyAppView 的构造函数中。它应该如下所示

CMyAppView::CMyAppView()
{
  m_strClass=TEXT("RichEdit50W");
  //Must be m_strClass, it is a member of CCtrlView
  ...
}

然后,将 'LoadLibrary(TEXT("msftedit.dll"));' 放入 CMyApp 类的构造函数中。并且,必须初始化 OLE。完成后,它应该如下所示

CMyApp::CMyApp()
{
 CoInitialize(NULL); //this must be called FIRST!

 //m_hinstRE41 is a HINSTANCE type member var of CMyApp
 m_hinstRE41=LoadLibrary(TEXT("msftedit.dll"));
 //this DLL must be loaded.
 ...
}

CMyApp::~CMyApp()
{
 if(m_hinstRE41)
 FreeLibrary(m_hinstRE41);
}
CMyApp::InitInstance()
{
 AfxOleInit();                     //you don't want to miss this ....
 AfxEnableControlContainer();      //and this ....
 ...
}

另一个重要提示

CMyAppView::OnDestroy 中,您应该看到

void CGreatTracerView::OnDestroy()
{
  //CRichEditView::OnDestroy(); <------the MFC App Wiz put the codes here,
  // but it shouldn't.
  // Deactivate the item on destruction; this is important
  // when a splitter view is being used.
  COleClientItem* pActiveItem = GetDocument()->
               GetInPlaceActiveItem(this); //If OnDestroy() were still up there,
                                       //the app would CRASH here!
  if (pActiveItem != NULL && pActiveItem->GetActiveView() == this)
  {
     pActiveItem->Deactivate();
     ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  }
  CRichEditView::OnDestroy();
  // this codes should be here, so, everything is fine!
}

顺便说一下,我真的建议以 Unicode 方式构建项目。:)

历史

  • 2010.2.6:第一个版本 - 1.0。
  • 2010.2.7:版本 1.1 - 添加了更多介绍和原理部分。
  • 2010.2.23:版本 1.2 - 纠正了版本错误;msftedit.dll 包含富文本编辑控件 v4.1(类名为 RICHEDIT50W),而不是 v5.0。
© . All rights reserved.