PRB: RichEdit Control in Applications That Call OleInitialize()
ID: Q238989
|
The information in this article applies to:
-
The Microsoft Foundation Classes (MFC), included with:
-
Microsoft Visual C++, 32-bit Editions, versions 5.0, 6.0
SYMPTOMS
When using the RichEdit control in an application that calls OleInitialize, if the control is destroyed during a Component Object Model (COM) call, then OLE will not be uninitialized correctly.
CAUSE
The problem occurs because the RichEdit control, by default, calls OleInitialize when it is initialized, and calls OleUninitialize when it is destroyed. If the application is in the context of a COM call when it destroys the RichEdit window, then OleUninitialize will not run correctly, because OleUninitialize ends up calling CoUninitialize, and CoUninitialize will return immediately if the thread is in the context of another COM call. This results in an unbalanced call to CoInitialize, and therefore the OLE libraries are not uninitialized correctly.
Please note this problem applies only to RichEdit 1.0.
A known issue with this problem is if the RichEdit control is used in an Active Document Server, and the server destroys the RichEdit control within the context of the IOleObject::Close call. This happens in MFC when the RichEdit control is destroyed when the view, or the document, is being destroyed.
RESOLUTION
To work around this issue, the RichEdit control should be created so that it will not call OleInitialize and OleUninitialize. To do this, set the ES_EX_NOCALLOLEINIT style during the WM_NCCREATE message, before the RichEdit control handles this message.
The following steps describe how to do this in MFC:
- Create a class that is derived from CRichEditCtrl:
class CMyRichEdit : public CRichEditCtrl
{
DECLARE_DYNCREATE(CMyRichEdit)
public:
CMyRichEdit(){};
~CMyRichEdit(){};
//{{AFX_MSG(CMyRichEdit)
afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
- Add the message map and entries as follows in the *.cpp file for the class:
IMPLEMENT_DYNCREATE(CMyRichEdit, CRichEditCtrl)
BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
//{{AFX_MSG_MAP(CMyRichEdit)
ON_WM_NCCREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
- Handle the OnNcCreate function as follows:
BOOL CMyRichEdit::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
LONG gwlEx = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
gwlEx |= ES_EX_NOCALLOLEINIT;
gwlEx = ::SetWindowLong(m_hWnd, GWL_EXSTYLE, gwlEx);
if (!CRichEditCtrl::OnNcCreate(lpCreateStruct))
return FALSE;
return TRUE;
}
Use GetWindowLong and SetWindowLong to add the ES_EX_NOCALOLEINIT style to the control. This method must be used because the RichEdit control does not pay attention to this extended style when creating the control through CreateWindowEx.
STATUS
This behavior is by design.
MORE INFORMATION
Steps to Reproduce Behavior
- Use AppWizard to create an MFC MDI Active Document Container.
- Build the Active Document Container.
- Use AppWizard to create an MFC Active Document Server.
- Make sure that AfxOleInit is called in the InitInstance function in the Active Document Server's CWinApp-derived class.
- Add the following member variable declaration to the CView-derived class of the server:
CRichEditCtrl m_RichEdit;
- Use class wizard to add a message handler for WM_CREATE in the CView-derived class of the server.
- Add the following code to the OnCreate message handler added above:
m_RichEdit.Create(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL | ES_SAVESEL
, CRect(0,0,1,1), this, 2001);
- Add the following code to the destructor of the CView-derived class:
m_RichEdit.DestroyWindow();
- Build the Active Document Server.
- Run the Active Document Container and insert the Active Document Server.
- Close the MDI Child window that the server is in.
- Close the Active Document Container.
Notice that the container process is still running.
Additional query words:
Keywords : kbActiveDocs kbActiveX kbCOMt kbContainer kbCtrl kbMFC kbRichEdit kbVC500 kbVC600 kbDSupport kbGrpMFCATL
Version : winnt:5.0,6.0
Platform : winnt
Issue type : kbprb