- 不能夠自動初始化
- 不能夠接受TAB鍵
- 不能夠通過屬性設置自動換行
- 不能顯示圖片等其他OLE對象
- 不能夠使用Ctrl+C來實現拷貝
不能夠自動初始化
當我第一次將Rich Edit控件放在資源窗體上的時候,發現程序根本就不能運行。后來才找到原因,原來Rich Edit 控件是Ole類型的控件。在加載Rich Edit 控件的時候,必須進行初始化。代碼如下:
BOOLCTestApp::InitInstance(){
.....
AfxInitRichEdit();
}
不能夠接受TAB鍵
將 RichEdit控件放到資源窗體上的時候,發現它的屬性頁中并沒有設置接受TAB鍵的設置,導致當把焦點放到Rich Edit 控件上的時候,一按tab鍵,焦點就移動到下一個控件上面去了。
具體解決方法就是重載Rich Edit控件的OnGetDlgCode:
例子代碼:
.h文件:
class CMyRichEdit : public CRichEditCtrl{
........
afx_msg UINT OnGetDlgCode( );
........
}
.cpp文件:
BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
ON_WM_GETDLGCODE( )
END_MESSAGE_MAP()
UINT COleRichEditCtrl::OnGetDlgCode( ){
return DLGC_WANTTAB;
}
不能夠通過屬性設置自動換行
當把Rich Edit控件放到資源窗體上的時候,發現在它的屬性窗體中并沒有設置Rich Edit控件自動換行的屬性設置。要達到這一目的,例子代碼如下:
BOOL CTestDlg::InitDialog(){
.............
//m_RichEdit為窗體類的成員變量
this->m_RichEdit.SetTargetDevice(NULL,0);
............
}
不能顯示圖片等其他OLE對象
MFC提供的CRichEditCtrl沒有提供直接顯示圖片等OLE對象的屬性或方法設置,但是提供了一個接口SetOLECallback( IRichEditOleCallback* pCallback );
要讓CRichEditCtrl顯示圖片,就得在IRichEditOleCallback上下功夫。
IRichEditOleCallback是windows中的接口,它的定義如下:
ContextSensitiveHelp:
通過該方法通知應用程序它將以上下文關聯方式調度幫助。
DeleteObject:
通過該方法發出通知:一個對象即將從RichEdit控件中刪除
GetClipboardData:
通過該方法允許RichEdit的客戶端(調用程序)提供自己的粘貼對象
GetContextMenu:
通過該方法向應用程序提出通過鼠標右鍵事件來獲取上下文菜單的請求
GetDragDropEffect:
通過該方法允許RichEdit的客戶端(調用程序)設置拖動操作的效果
GetInPlaceContext:
通過該方法提供了應用程序級和文檔級接口,以及必要的支持In-place激活的信息
GetNewStrorage:
通過該方法存儲從粘貼板或超文本流(RTF)中讀取的新對象
QueryAcceptData:
通過該方法決定在粘貼操作或拖放操作中引入的數據是否可以被接受。
QueryInsertObject:
通過該方法向應用程序詢問某個對象是否可以被插入
ShowContainerUI:
通過該方法告知應用程序是否顯示自己的操作界面
大致了解了IRichEditOleCallback接口后,就應該清楚,要顯示圖片等ole對象,至少應該實現GetNewStorage方法,因為該方法是存儲ole對象的接口方法。
以下是接口聲明的代碼:
interface IExRichEditOleCallback : IRichEditOleCallback
{
public:
IExRichEditOleCallback();
virtual ~IExRichEditOleCallback();
int m_iNumStorages;
IStorage* pStorage;
DWORD m_dwRef;
virtual HRESULT STDMETHODCALLTYPE GetNewStorage(LPSTORAGE* lplpstg);
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
virtual HRESULT STDMETHODCALLTYPE GetInPlaceContext(LPOLEINPLACEFRAME FAR *lplpFrame,
LPOLEINPLACEUIWINDOW FAR *lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo);
virtual HRESULT STDMETHODCALLTYPE ShowContainerUI(BOOL fShow);
virtual HRESULT STDMETHODCALLTYPE QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp);
virtual HRESULT STDMETHODCALLTYPE DeleteObject(LPOLEOBJECT lpoleobj);
virtual HRESULT STDMETHODCALLTYPE QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT FAR *lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict);
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
virtual HRESULT STDMETHODCALLTYPE GetClipboardData(CHARRANGE FAR *lpchrg, DWORD reco, LPDATAOBJECT FAR *lplpdataobj);
virtual HRESULT STDMETHODCALLTYPE GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect);
virtual HRESULT STDMETHODCALLTYPE GetContextMenu(WORD seltyp, LPOLEOBJECT lpoleobj, CHARRANGE FAR *lpchrg, HMENU FAR *lphmenu);
}
關于接口的實現,將被附在最后的附錄中。
不能夠使用Ctrl+C來實現拷貝
實際上,CRichEditCtrl本身是支持Ctrl+C實現拷貝功能的,但是當我在CRichiEditCtrl的繼承類中使用了IRichiEditCallback接口后,它就不在支持Ctrl+C實現拷貝功能了。我想問題就出在IRichEditCallback接口上。
仔細看了一遍它的幫助文檔,我發現問題就出在GetClipboardData上,我沒有在它的實現方法中寫代碼,只是返回了S_OK,如果要處理Ctrl+C,就必須返回E_NOTIMPL。
以上是我近幾天的開發經歷,與大家分享,還希望路過的高手多多指教。
在以下關于RichEdit的代碼例子中,我參考了Mike O'Neill 的代碼,再次謝謝他的貢獻。
附錄
.h文件
#if !defined(AFX_OLERICHEDITCTRL_H__3DFF15EE_7336_4297_9620_7F00B611DAA1__INCLUDED_)
#define AFX_OLERICHEDITCTRL_H__3DFF15EE_7336_4297_9620_7F00B611DAA1__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// OleRichEditCtrl.h : header file
//
#i nclude < richole.h >
/////////////////////////////////////////////////////////////////////////// //
// COleRichEditCtrl window
class COleRichEditCtrl : public CRichEditCtrl
{
// Construction
public :
COleRichEditCtrl();
virtual ~ COleRichEditCtrl();
long StreamInFromResource( int iRes, LPCTSTR sType);
protected :
static DWORD CALLBACK readFunction(DWORD dwCookie,
LPBYTE lpBuf, // the buffer to fill
LONG nCount, // number of bytes to read
LONG * nRead); // number of bytes actually read
interface IExRichEditOleCallback; // forward declaration (see below in this header file)
IExRichEditOleCallback * m_pIRichEditOleCallback;
BOOL m_bCallbackSet;
interface IExRichEditOleCallback : public IRichEditOleCallback
{
public :
IExRichEditOleCallback();
virtual ~ IExRichEditOleCallback();
int m_iNumStorages;
IStorage * pStorage;
DWORD m_dwRef;
virtual HRESULT STDMETHODCALLTYPE GetNewStorage(LPSTORAGE * lplpstg);
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
virtual HRESULT STDMETHODCALLTYPE GetInPlaceContext(LPOLEINPLACEFRAME FAR * lplpFrame,
LPOLEINPLACEUIWINDOW FAR * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo);
virtual HRESULT STDMETHODCALLTYPE ShowContainerUI(BOOL fShow);
virtual HRESULT STDMETHODCALLTYPE QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp);
virtual HRESULT STDMETHODCALLTYPE DeleteObject(LPOLEOBJECT lpoleobj);
virtual HRESULT STDMETHODCALLTYPE QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT FAR * lpcfFormat,
DWORD reco, BOOL fReally, HGLOBAL hMetaPict);
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
virtual HRESULT STDMETHODCALLTYPE GetClipboardData(CHARRANGE FAR * lpchrg, DWORD reco, LPDATAOBJECT FAR * lplpdataobj);
virtual HRESULT STDMETHODCALLTYPE GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect);
virtual HRESULT STDMETHODCALLTYPE GetContextMenu(WORD seltyp, LPOLEOBJECT lpoleobj, CHARRANGE FAR * lpchrg,
HMENU FAR * lphmenu);
};
public :
// Overrides
// ClassWizard generated virtual function overrides
// {{AFX_VIRTUAL(COleRichEditCtrl)
protected :
virtual void PreSubclassWindow();
// }}AFX_VIRTUAL
// Implementation
public :
// Generated message map functions
protected :
// {{AFX_MSG(COleRichEditCtrl)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
// }}AFX_MSG
afx_msg UINT OnGetDlgCode( );
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////// //
// {{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_OLERICHEDITCTRL_H__3DFF15EE_7336_4297_9620_7F00B611DAA1__INCLUDED_)
.cpp文件
// OleRichEditCtrl.cpp : implementation file
//
#i nclude " stdafx.h "
#i nclude " OleRichEditCtrl.h "
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////// //
// COleRichEditCtrl
COleRichEditCtrl::COleRichEditCtrl()
{
m_bCallbackSet = FALSE;
}
COleRichEditCtrl:: ~ COleRichEditCtrl()
{
// IExRichEditOleCallback class is a reference-counted class
// which deletes itself and for which delete should not be called
// delete m_pIRichEditOleCallback;
}
BEGIN_MESSAGE_MAP(COleRichEditCtrl, CRichEditCtrl)
// {{AFX_MSG_MAP(COleRichEditCtrl)
ON_WM_CREATE()
// }}AFX_MSG_MAP
ON_WM_GETDLGCODE( )
END_MESSAGE_MAP()
//
int COleRichEditCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CRichEditCtrl::OnCreate(lpCreateStruct) == - 1 )
return - 1 ;
// m_pIRichEditOleCallback should have been created in PreSubclassWindow
ASSERT( m_pIRichEditOleCallback != NULL );
// set the IExRichEditOleCallback pointer if it wasn't set
// successfully in PreSubclassWindow
if ( ! m_bCallbackSet )
{
SetOLECallback( m_pIRichEditOleCallback );
}
return 0 ;
}
void COleRichEditCtrl::PreSubclassWindow()
{
// base class first
CRichEditCtrl::PreSubclassWindow();
m_pIRichEditOleCallback = NULL;
m_pIRichEditOleCallback = new IExRichEditOleCallback;
ASSERT( m_pIRichEditOleCallback != NULL );
m_bCallbackSet = SetOLECallback( m_pIRichEditOleCallback );
}
long COleRichEditCtrl::StreamInFromResource( int iRes, LPCTSTR sType)
{
HINSTANCE hInst = AfxGetInstanceHandle();
HRSRC hRsrc = ::FindResource(hInst,
MAKEINTRESOURCE(iRes), sType);
DWORD len = SizeofResource(hInst, hRsrc);
BYTE * lpRsrc = (BYTE * )LoadResource(hInst, hRsrc);
ASSERT(lpRsrc);
CMemFile mfile;
mfile.Attach(lpRsrc, len);
EDITSTREAM es;
es.pfnCallback = readFunction;
es.dwError = 0 ;
es.dwCookie = (DWORD) & mfile;
return StreamIn( SF_RTF, es );
}
/* static */
DWORD CALLBACK COleRichEditCtrl::readFunction(DWORD dwCookie,
LPBYTE lpBuf, // the buffer to fill
LONG nCount, // number of bytes to read
LONG * nRead) // number of bytes actually read
{
CFile * fp = (CFile * )dwCookie;
* nRead = fp -> Read(lpBuf,nCount);
return 0 ;
}
/////////////////////////////////////////////////////////////////////////// //
COleRichEditCtrl::IExRichEditOleCallback::IExRichEditOleCallback()
{
pStorage = NULL;
m_iNumStorages = 0 ;
m_dwRef = 0 ;
// set up OLE storage
HRESULT hResult = ::StgCreateDocfile(NULL,
STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE /* | STGM_DELETEONRELEASE */ | STGM_CREATE ,
0 , & pStorage );
if ( pStorage == NULL ||
hResult != S_OK )
{
AfxThrowOleException( hResult );
}
}
COleRichEditCtrl::IExRichEditOleCallback:: ~ IExRichEditOleCallback()
{
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetNewStorage(LPSTORAGE * lplpstg)
{
m_iNumStorages ++ ;
WCHAR tName[ 50 ];
swprintf(tName, L " REOLEStorage%d " , m_iNumStorages);
HRESULT hResult = pStorage -> CreateStorage(tName,
STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE ,
0 , 0 , lplpstg );
if (hResult != S_OK )
{
::AfxThrowOleException( hResult );
}
return hResult;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::QueryInterface(REFIID iid, void ** ppvObject)
{
HRESULT hr = S_OK;
* ppvObject = NULL;
if ( iid == IID_IUnknown ||
iid == IID_IRichEditOleCallback )
{
* ppvObject = this ;
AddRef();
hr = NOERROR;
}
else
{
hr = E_NOINTERFACE;
}
return hr;
}
ULONG STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::AddRef()
{
return ++ m_dwRef;
}
ULONG STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::Release()
{
if ( -- m_dwRef == 0 )
{
delete this ;
return 0 ;
}
return m_dwRef;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetInPlaceContext(LPOLEINPLACEFRAME FAR * lplpFrame,
LPOLEINPLACEUIWINDOW FAR * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::ShowContainerUI(BOOL fShow)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::DeleteObject(LPOLEOBJECT lpoleobj)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT FAR * lpcfFormat,
DWORD reco, BOOL fReally, HGLOBAL hMetaPict)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::ContextSensitiveHelp(BOOL fEnterMode)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetClipboardData(CHARRANGE FAR * lpchrg, DWORD reco, LPDATAOBJECT FAR * lplpdataobj)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetContextMenu(WORD seltyp, LPOLEOBJECT lpoleobj, CHARRANGE FAR * lpchrg,
HMENU FAR * lphmenu)
{
return S_OK;
}
// TabRichEditCtrl 消息處理程序
UINT COleRichEditCtrl::OnGetDlgCode( ){
return DLGC_WANTTAB;
}