PRB: Menus Either Do Not Work or They Cause a Crash in the MFC MDI ActiveX Document Container
ID: Q243315
|
The information in this article applies to:
-
Microsoft Visual C++, 32-bit Professional Edition, version 6.0
-
The Microsoft Foundation Classes (MFC)
-
Microsoft Excel 2000
SYMPTOMS
After switching between MDI documents in an MFC MDI ActiveX Document Container, the ActiveX Document Server's merged menus fail to work properly, or cause a crash with a message such as:
The instruction at "0x303820bc" referenced memory at "0x00000000". The memory could not be "read."
CAUSE
Some servers, such as Microsoft Excel 2000, need to be de-activated and re-activated every time they are activated in an MDI ActiveX Document Container.
RESOLUTION
To resolve the problem, each time an MDI view that contains a server is activated, you must de-activate and re-activate the server. See the sample below for complete steps.
MORE INFORMATIONSteps to Reproduce Behavior
- Using Visual C++ 6.0, create a new MFC AppWizard (exe0 project named MdiAdxPrb.
- Select Multiple documents in step 1, and click Next twice.
- Select Container, check Active document container, then click Finish.
- Compile and run the project.
- From the Insert menu drop down box, choose Object, and insert a Microsoft Excel Worksheet.
- From the File menu, select New.
- From the Insert menu drop down box, choose Object again and insert another Microsoft Excel Worksheet.
- Note that if you choose a menu option from the newly-merged Microsoft Excel menus, such as Format|Cells, it responds appropriately.
- Now, click from this MDI child window back to the first one, and try selecting the same menu item.
The result is that either the menu does not work, or it causes a crash.
Steps to Work Around Behavior
- Using the first three steps from the section above, build an MDI ActiveX Document container.
- Open MdiAdxPrbView.h and add the following member variable and function declaration to the top of the CMdiAdxPrbView class:
int m_viewID; // view id...
LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
- Open MdiAdxPrbView.cpp, and add the following global variables just before the CMdiAdxPrbView constructor:
int g_nextViewID = 1;
int g_activeViewID = 0;
- In the CMdiAdxPrbView constructor, add the following lines of code:
m_viewID = g_nextViewID;
g_nextViewID++;
- In MdiAdxPrbView.cpp, add the following line to your CMdiAdxPrbView message map:
ON_MESSAGE(WM_APP+1, OnMyMessage)
- Hit the CTRL+W keys to bring up the ClassWizard, and add a handler for OnActivateView in your CMdiAdxPrbView class.
- Add the following lines of code to the end of the implementation in OnActivateView():
if (bActivate && m_pSelection) {
if (m_viewID != g_activeViewID) {
g_activeViewID = m_viewID;
PostMessage(WM_APP+1);
}
}
- Add the following function to the end of your MdiAdxPrbView.cpp file:
LRESULT CMdiAdxPrbView::OnMyMessage(WPARAM wParam, LPARAM lParam) {
if (m_pSelection) {
m_pSelection->Deactivate();
m_pSelection->Activate(OLEIVERB_UIACTIVATE, this);
}
return 0;
}
- Compile and Run.
The code basically overrides OnActivateView() to be notified whenever a view is activated, and de-activates and re-activates any active server in that view if it has not already been activated. You have to post a message from OnActivateView() because the calls De-activate and Activate you want to make are not allowed in a synchronous context.
Additional query words:
Keywords : kbActiveDocs kbActiveX kbExcel kbMFC kbVC600 kbGrpDSO kbDSupport
Version : WINDOWS:2000; winnt:6.0
Platform : WINDOWS winnt
Issue type : kbprb
|