FIX: DocObject Server with OCX in View Causes ASSERT in IE (190964)



The information in this article applies to:

  • The Microsoft Foundation Classes (MFC), when used with:
    • Microsoft Visual C++, 32-bit Enterprise Edition 6.0
    • Microsoft Visual C++, 32-bit Professional Edition 6.0
    • Microsoft Visual C++, 32-bit Learning Edition 6.0

This article was previously published under Q190964

SYMPTOMS

DocObject server with ActiveX controls in its view will assert (WINMDI.CPP Line 341) when navigating pages in Internet Explorer version 4.01.

CAUSE

The SendMessage() with WM_MDIGETACTIVE in the code of CMDIFrameWnd::MDIGetActive() function is returning an invalid window handle (HWND).

RESOLUTION

To correct the problem, we must check the validity of the HWND returned by processing WM_MDIGETACTIVE message, and set the HWND to NULL if it's not valid. Below are the listed steps:
  1. Subclass the MDI client to intercept the WM_MDIGETACTIVE message.

    For additional information that shows how to subclass the MDICLIENT window, please see the following article in the Microsoft Knowledge Base:

    129471 How to SubClass the MDIClient by Using MFC

  2. Handle the WM_MDIGETACTIVE message in the MDI client as follow:
          // CMDIClientWnd is the MDI client window. OnMdiGetActivate() is
          // the message handler for WM_MDIGETACTIVE.
          BEGIN_MESSAGE_MAP(CMDIClientWnd, CWnd)
             //{{AFX_MSG_MAP(CMDIClientWnd)
             //}}AFX_MSG_MAP
             ON_MESSAGE(WM_MDIGETACTIVE, OnMdiGetActivate)
          END_MESSAGE_MAP()
    
          // Validate the HWND returned from processing the WM_MDIGETACTIVE
          // in the default window procedure. Returns NULL if an invalid MDI
          // child window is found.
          afx_msg LRESULT CMDIClientWnd::OnMdiGetActivate(WPARAM, LPARAM)
          {
             LRESULT rvalue = Default();
             if (rvalue)
             {
                CMDIChildWnd* pWnd =
                   (CMDIChildWnd*)CWnd::FromHandle((HWND) rvalue);
                if (pWnd &&
                    pWnd->IsKindOf(RUNTIME_CLASS(CMDIChildWnd)) == 0)
                {
                   return NULL;
                }
             }
    
             return rvalue;
         }

STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article.

This problem was corrected in Microsoft Visual C++ .NET.

MORE INFORMATION

Steps to Reproduce Behavior

  1. Create a generic MDI-based ActiveX Document server (also called DocObject server) with the AppWizard. For illustration purpose, set the file extension as .xab.
  2. Add a CWnd member variable called m_Control to your CView-derived class.
  3. Add a message handler for WM_CREATE in your CView-derived class. Initialize m_Control by calling CreateControl() to dynamically create a visible ActiveX control in the view.
  4. Build and run the application.
  5. On the File menu, click Save to save the file (for example, c:\test.xab), and exit the application.
  6. Start Internet Explorer 4.01 and navigate to a web page (for example, http://www.microsoft.com).
  7. Type c:\test.xab into address window of Internet Explorer 4.01, and press ENTER.
  8. Click the ActiveX control in the ActiveX document server's view window.
  9. Click the Internet Explorer 4.01 Back button to navigate back to "http://www.microsoft.com."
  10. Click the Internet Explore 4.01 Forward button to navigate back to the c:\test.xab file. You will hit an assert in MdiFrameWnd::MDIGetActive(). Specifically, you'll hit an assert in the following code:
          CMDIChildWnd* CMDIFrameWnd::MDIGetActive(BOOL* pbMaximized) const
          {
     
             // Check first for MDI client window not created.
             if (m_hWndMDIClient == NULL){
                if (pbMaximized != NULL)
                   *pbMaximized = FALSE;
                return NULL;
             }
    
             // MDI client has been created, get active MDI child.
             HWND hWnd = (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE,
                0, (LPARAM)pbMaximized);
             CMDIChildWnd* pWnd = (CMDIChildWnd*)CWnd::FromHandle(hWnd);
            ASSERT(pWnd == NULL ||         pWnd-
       >IsKindOf(RUNTIME_CLASS(CMDIChildWnd)));//>-- ASSERTS HERE
            ...
           }
    						

REFERENCES

For additional information, please see the following article in the Microsoft Knowledge Base:

129471 How to SubClass the MDIClient by Using MFC


Modification Type:MajorLast Reviewed:12/10/2003
Keywords:kbBug kbfix kbNoUpdate KB190964 kbAudDeveloper