PRB: FromIDispatch Returns NULL for OLE Control

Last reviewed: July 31, 1997
Article ID: Q138414
2.00 2.10 | 1.50 1.51 1.52 1.52a WINDOWS NT | WINDOWS kbprg kbtshoot kbprb

The information in this article applies to:

  • The Microsoft Foundation Classes (MFC) included with:

        - Microsoft Visual C++, 32-bit Edition, versions 2.0, 2.1
        - Microsoft Visual C++ for Windows, versions 1.5, 1.51, 1.52, 1.52a
    

SYMPTOMS

Calling CCmdTarget::FromIDispatch() inside a member function of a class derived from COleControl or attempting to call FromIDispatch() passing an IDispatch pointer belonging to an OLE Control, will always return NULL.

CAUSE

CCmdTarget::FromIDispatch() does the following test to determine if the passed IDispatch pointer belongs to a CCmdTarget-derived class or not:

    COleDispatchImpl dispatch;

    ASSERT(*(DWORD*)&dispatch != 0);    // null vtable ptr?
    if (*(DWORD*)lpDispatch != *(DWORD*)&dispatch)
        return NULL;    // not our Idispatch*

The problem here is that classes derived from COleControl don't use the COleDispatchImpl implementation of IDispatch directly. They have their own implementation using BEGIN_INTERFACE_PART and END_INTERFACE_PART that delegates to the COleDispatchImpl object in the CCmdTarget base class. Because of this, the v-tables in the previous test won't match and the function will return NULL.

RESOLUTION

It is possible to access the object of the class derived from COleControl given a valid IDispatch pointer. The object can be accessed from another control or outside of a control with the aid of a helper control. A helper control would be necessary because the following formula relies on details that are internal to a COleControl class.

To access the object of the class derived from COleControl successfully, you need to use a formula similar to this one:

   COleControl * pCtrl = (COleControl*)
       ((BYTE*)lpDisp - m_xDispatch.m_nOffset);

In this formula, lpDisp is a valid LPDISPATCH, m_xDispatch is the XDispatch object member of COleControl that contains the control's implementation of IDispatch, and m_nOffset is the offset generated by the INIT_INTERFACE_PART macro for IDispatch.

m_xDispatch is generated by the END_INTERFACE_PART macro as follows:

   #define END_INTERFACE_PART(localClass) \
      } m_x##localClass; \
      friend class X##localClass; \

In this case, localClass is "Dispatch" so m_x##localClass becomes m_xDispatch.

m_nOffset is generated by the INIT_INTERFACE_PART macro as follows:

    #ifndef _AFX_NO_NESTED_DERIVATION
    #define INIT_INTERFACE_PART(theClass, localClass) \
          size_t m_nOffset; \
             INIT_INTERFACE_PART_DERIVE(theClass,localClass) \

    #define INIT_INTERFACE_PART_DERIVE(theClass, localClass) \
          X##localClass() \
        { m_nOffset = offsetof(theClass, m_x##localClass); } \

m_nOffset becomes offsetof(COleControl, m_xDispatch).

STATUS

This behavior is by design.

MORE INFORMATION

This difference between CCmdTarget and COleControl's implementation of IDispatch disappears in Visual C++ version 4.0. COleControl uses COleDispatchImpl in version 4.0 and therefore, FromIDispatch() will work.


Additional reference words: 2.00 2.10 1.50 1.51 1.52 1.52a
KBCategory: kbprg kbtshoot kbprb
KBSubcategory: CDKIss
Technology : kbMfc
Version : 2.00 2.10 | 1.50 1.51 1.52 1.52


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 31, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.