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;
void Stream(CXArchive& Ar, bool bSelection)
{
ATLASSERT(::IsWindow(m_hWnd));
int nFormat;
EDITSTREAM es = {0, 0, EditStreamCallBack};
es.dwCookie = (DWORD)&Ar;
if (m_bRTF)
nFormat = SF_RTF;
else
nFormat = SF_TEXT;
if (bSelection)
nFormat |= SFF_SELECTION;
if (Ar.IsStoring())
StreamOut(nFormat, es);
else
{
StreamIn(nFormat, es);
Invalidate();
}
}
static DWORD CALLBACK EditStreamCallBack(DWORD dwCookie,
LPBYTE pbBuff, LONG cb, LONG *pcb)
{
ATLASSERT(dwCookie != 0);
ATLASSERT(pcb != NULL);
DWORD dwRet = 0;
CXArchive * pAr = (CXArchive*)dwCookie;
pAr->Flush();
*pcb = cb;
try
{
if (pAr->IsStoring())
pAr->GetFile()->Write(pbBuff, cb);
else
*pcb = pAr->GetFile()->Read(pbBuff, cb);
}
catch(CXException& e)
{
*pcb = 0;
dwRet = e.GetErrorNumber();
}
return dwRet;
}
public:
DECLARE_WND_SUPERCLASS(NULL, CRichEditCtrl::GetWndClassName())
CRichEditEx()
{
m_bRTF = true;
}
BOOL PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}
BEGIN_MSG_MAP(CRichEditEx)
END_MSG_MAP()
void SetStreamFormat(bool bRTF)
{
m_bRTF = bRTF;
}
bool GetStreamFormat()
{
return m_bRTF;
}
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 , WORD ,
HWND , BOOL& )
{
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 , WORD ,
HWND , BOOL& )
{
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.