Click here to Skip to main content
Licence CPOL
First Posted 11 Oct 2004
Views 27,684
Bookmarked 10 times

How to add serialization support to WTL CRichEditCtrl class

By | 13 Oct 2004 | Article
Small class that adds a serialization support to CRichEditCtrl class

Introduction

WTL comes with many control classes that provide standard elements of the user interface. One of them is CRichEditCtrl - a rich edit control that understands some basic RTF formatting and allows multiple fonts, colors, and so on. But some useful features that it's MFC counterpart has are missing in the WTL implementation, one of them being able to serialize CRichEditCtrl.

So I wrote a small class CRichEditEx that adds a serialization support to CRichEditCtrl class. This class is using CXArchive class [^] also developed by me and, basically, a port of MFC code.

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

Using the code

1. Derive your class from CRichEditEx like so:

class CRichEditDemoView : public CRichEditEx<CRichEditDemoView>
{
 ...
};
2. Add CXFile and CXArchive classes to your project:
#include "File.h"
#include "Archive.h"
3. Somewhere in your code where you want to save the contents of the rich edit control add the following code:
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. Somewhere in your code where you want to load the contents of the rich edit control from the file add the following code:
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;
}

Demo project

Demo project contains the CRichEditEx, CXArchive, CXFile classes implementations and example how to use them.

Selecting File->Save will store the contents of the rich edit control into the file and File->Open will insert text into the rich edit control.

History

  • October 12, 2004 - initial release.
  • October 13, 2004 - bug fix, where methods of the class derived from CRichEditEx can't be called by CWindowImpl. Thanks to Stuart Dootson for pointing it out.

Disclaimer

THIS SOFTWARE AND THE ACCOMPANYING FILES ARE DISTRIBUTED "AS IS" AND WITHOUT ANY WARRANTIES WHETHER EXPRESSED OR IMPLIED. NO RESPONSIBILITIES FOR POSSIBLE DAMAGES CAN BE TAKEN. THE USER MUST ASSUME THE ENTIRE RISK OF USING THIS SOFTWARE.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Igor Vigdorchik

Web Developer

United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralWhy is CRichEditEx a template... PinmemberStuart Dootson1:12 12 Oct '04  
GeneralRe: Why is CRichEditEx a template... PinmemberIgor Vigdorchik7:44 12 Oct '04  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 14 Oct 2004
Article Copyright 2004 by Igor Vigdorchik
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid