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

如何为 WTL CRichEditCtrl 类添加序列化支持

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.08/5 (5投票s)

2004年10月12日

CPOL

1分钟阅读

viewsIcon

41100

downloadIcon

769

一个小型类,为 CRichEditCtrl 类添加序列化支持。

引言

WTL 包含许多控件类,提供标准的界面元素。其中之一是 CRichEditCtrl - 一个富文本编辑控件,它理解一些基本的 RTF 格式,并允许使用多种字体、颜色等。但是,WTL 实现中缺少 MFC 对应版本的一些有用功能,其中之一就是无法序列化 CRichEditCtrl

因此,我编写了一个小类 CRichEditEx,为 CRichEditCtrl 类添加了序列化支持。该类使用 CXArchive 类 [^],该类也是由我开发的,基本上是 MFC 代码的移植。

CRichEditEx

template <class T>
class CRichEditEx : public CWindowImpl<T, CRichEditCtrl>
{
private:
 bool m_bRTF; // when true, indicates 
   // that CRichEditCtrl should store paragraph
   // and character-formatting characteristics.

 /************************************************************
 * Function......: Stream
 * Parameters....: Ar - archive class
 *  bSelection - indicates whether only selected text should
 *  be saved or read
 * Returns.......: None
 * Description...: Transfers data into or out of a rich edit control
 ************************************************************/
 void Stream(CXArchive& Ar, bool bSelection)
 {
  ATLASSERT(::IsWindow(m_hWnd));
  int nFormat; // indicates whether stream I/O should include formatting

  EDITSTREAM es = {0, 0, EditStreamCallBack};
  es.dwCookie = (DWORD)&Ar;

  if (m_bRTF)  // rich edit control maintains formatting information
   nFormat = SF_RTF;
  else   // rich edit control does not maintain formatting information
   nFormat = SF_TEXT;

  if (bSelection)
   nFormat |= SFF_SELECTION;

  if (Ar.IsStoring())
   // Store text from the rich edit control into an output stream
   StreamOut(nFormat, es);
  else
  {
   // Insert text from an input stream into the rich edit control
   StreamIn(nFormat, es);
   Invalidate();
  }
 }

 /******************************************************************
 * Function......: EditStreamCallBack
 * Parameters....: dwCookie - application-defined value
 *  pbBuff - data buffer
 *  cb - number of bytes to read or write
 *  pcb - number of bytes transferred
 * Returns.......: Returns 0 if no error, otherwise return error code
 * Description...: Application defined callback function  
 *  used to transfer a stream of data into or out of a rich edit control
 ******************************************************************/
 static DWORD CALLBACK EditStreamCallBack(DWORD dwCookie,
   LPBYTE pbBuff, LONG cb, LONG *pcb)
 {
  ATLASSERT(dwCookie != 0);
  ATLASSERT(pcb != NULL);
  
  DWORD dwRet = 0;

  // Retrieve an archive object
  CXArchive * pAr = (CXArchive*)dwCookie;

  pAr->Flush();

  *pcb = cb;

  try
  {
   if (pAr->IsStoring())
    // Save text
    pAr->GetFile()->Write(pbBuff, cb);
   else
    // Load test
    *pcb = pAr->GetFile()->Read(pbBuff, cb);
  }
  catch(CXException& e)
  {
   *pcb = 0;
   dwRet = e.GetErrorNumber();
  }

  return dwRet;
 }

public:
 DECLARE_WND_SUPERCLASS(NULL, CRichEditCtrl::GetWndClassName())

 /******************************************************************
 * Function......: Constructor
 * Parameters....: None
 * Returns.......: None
 * Description...: Initializes a class object
 *******************************************************************/
 CRichEditEx()
 {
  m_bRTF = true;
 }

 BOOL PreTranslateMessage(MSG* pMsg)
 {
  pMsg;
  return FALSE;
 }

 BEGIN_MSG_MAP(CRichEditEx)
 END_MSG_MAP()

 /*****************************************************************
 * Function......: SetStreamFormat
 * Parameters....: Formatting flag value
 * Returns.......: None
 * Description...: Sets a formatting flag
 ****************************************************************/
 void SetStreamFormat(bool bRTF)
 {
  m_bRTF = bRTF;
 }

 /*****************************************************************
 * Function......: GetStreamFormat
 * Parameters....: None
 * Returns.......: Formatting flag
 * Description...: Gets a formatting flag
 ***************************************************************/
 bool GetStreamFormat()
 {
  return m_bRTF;
 }

 /****************************************************************
 * Function......: Serialize
 * Parameters....: Ar - archive class
 * Returns.......: None
 * Description...: Reads/writes CRichEditCtrl object from/to archive
 ****************************************************************/
 void Serialize(CXArchive& Ar)
 {
  ATLASSERT(::IsWindow(m_hWnd));

  Stream(Ar, false);
 }
};

使用代码

1. 像这样从 CRichEditEx 派生您的类

class CRichEditDemoView : public CRichEditEx<CRichEditDemoView>
{
 ...
};
2. 将 CXFileCXArchive 类添加到您的项目中
#include "File.h"
#include "Archive.h"
3. 在您想要保存富文本编辑控件内容的任何代码位置,添加以下代码
LRESULT OnFileSave(WORD /*wNotifyCode*/, WORD /*wID*/, 
  HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
 string strFile = "demo.txt";
  
 try
 {
  CXFile file;
  file.Open(strFile,       
   GENERIC_WRITE | GENERIC_READ,   
   FILE_SHARE_READ | FILE_SHARE_WRITE,  
   NULL,         
   CREATE_ALWAYS,       
   FILE_ATTRIBUTE_NORMAL,     
   NULL);         
   
  CXArchive ar(&file, CXArchive::store);
   
  m_view.Serialize(ar);
   
  ar.Close();
 }
 catch (CXException& Ex)
 {
  MessageBox(Ex.GetErrorDesc().c_str(), _T("Richedit Demo"), MB_OK);
 }
 catch (...)
 {
  MessageBox(_T("Unexpected error"), _T("Richedit Demo"), MB_OK);
 }

 return 0;
}
4. 在您想要从文件中加载富文本编辑控件内容的任何代码位置,添加以下代码
LRESULT OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, 
  HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
 string strFile = "demo.txt";

 try
 {
  CXFile file;
  file.Open(strFile,       
   GENERIC_WRITE | GENERIC_READ,    
   FILE_SHARE_READ | FILE_SHARE_WRITE,  
   NULL,         
   OPEN_EXISTING,       
   FILE_ATTRIBUTE_NORMAL,     
   NULL);         
   
  CXArchive ar(&file, CXArchive::load);
   
  m_view.Serialize(ar);
   
  ar.Close();
 }
 catch (CXException& Ex)
 {
  MessageBox(Ex.GetErrorDesc().c_str(), _T("Richedit Demo"), MB_OK);
 }
 catch (...)
 {
  MessageBox(_T("Unexpected error"), _T("Richedit Demo"), MB_OK);
 }

 return 0;
}

演示项目

演示项目包含 CRichEditExCXArchiveCXFile 类的实现以及如何使用它们的示例。

选择“文件”->“保存”会将富文本编辑控件的内容存储到文件中,“文件”->“打开”会将文本插入到富文本编辑控件中。

历史

  • 2004 年 10 月 12 日 - 初始发布。
  • 2004 年 10 月 13 日 - 修复了一个错误,即从 CRichEditEx 派生的类的成员方法无法被 CWindowImpl 调用。感谢 Stuart Dootson 指出这一点。

免责声明

本软件及其附带的文件按“原样”分发,不提供任何形式的保证,无论是明示的还是暗示的。对于可能造成的任何损害,概不负责。用户必须承担使用本软件的全部风险。

© . All rights reserved.