1、用向导生成一个MFC ActiveX工程(MyTest)。2、给接口_DMyTest添加一个函数MyFunc,并编译生成ocx。3、用向导创建一个Dialog Base工程(Client),在ClientDlg.cpp中
   #import "..\MyTest\Debug\MyTest.ocx" no_namespace
   并
void CClientDlg::OnButton3() 
{
// TODO: Add your control notification handler code here
::CoInitialize(NULL);
{
_DMyTestPtr pCtl;
pCtl.CreateInstance(__uuidof(MyTest));
pCtl->MyFunc();
}
::CoUninitialize();
}4、编译发现在MyTest.tlh中
   _COM_SMARTPTR_TYPEDEF(_DMyTest, __uuidof(IDispatch));5、运行程序
   报错:“abnormal program termination”。6、调试,发现接口指针已经获取成功;只是在最后调用MyFunc的时候出错;而MyFunc是个空函数。

解决方案 »

  1.   

    你确信pCtl不是空的?怎么看都觉得这个智能指针有问题
      

  2.   

    pCtl.CreateInstance(__uuidof(MyTest));
    check its return value is E_OK?
      

  3.   

    在应用类的InitInstance里面是否调用了
    AfxEnableControlContainer();
    试试!
      

  4.   

    说明:我使用了好几种方法,包括CoCreateInstance,情况一样。
    问题好像出在
    _COM_SMARTPTR_TYPEDEF(_DMyTest, __uuidof(IDispatch));
    而ATL控件是:
    _COM_SMARTPTR_TYPEDEF(IMyTest, __uuidof(IMyTest));各位不妨一试!to dawndu(东南飞) :
    ——确信,因为F10每步,pCtl发生变化,并且非空。to kingzai(stevenzhu):
    ——是E_OK,也就是0,之前我写了判断语句,后来又改回来;并且调用AddRef是可以的!to hushuangyan74() :
    ——向导生成的Dialog Base程序,肯定是调用了的。
      

  5.   

    不好意思,我没有兴致去试,只是查看了下_com_ptr_t的源码,它在CreateInstance中使用其成员GetIID来获得接口,如果正常的话,猜测它应该返回
    _COM_SMARTPTR_TYPEDEF(_DMyTest, __uuidof(IDispatch));
    中的__uuidof(IDispatch),也就是IID_IDispatch,那么
    pCtl.CreateInstance(__uuidof(MyTest));
    后pCtl中的接口指针实际就是个IDispatch*,只不过在
    _COM_SMARTPTR_TYPEDEF(_DMyTest, __uuidof(IDispatch));
    被模板参数要求用_DMyTest来看待。那么这应该在编译时期产生类型不匹配的错误,不过在_com_ptr_t的源码中是使用下面的代码获得那个接口指针的
    hr = CoCreateInstance(rclsid, pOuter, dwClsContext, GetIID(), reinterpret_cast<void**>(&m_pInterface));
    即由于void**的屏蔽,编译器无法发现,进而在执行
    pCtl->MyFunc();
    时,pCtl.m_pInterface实际是IDispatch而不是_DMyTest,它的虚函数只有7个,而不是_DMyTest的8个(如果只增加了一个方法),所以当pCtl->MyFunc();时,它获得虚函数表中第8个项目的数值作为函数地址进行调用,那是无效的进而失败,也就是为什么调用AddRef是好的,因为它是虚函数表中的第一个项目。至于为什么会生成
    _COM_SMARTPTR_TYPEDEF(_DMyTest, __uuidof(IDispatch));
    而不是
    _COM_SMARTPTR_TYPEDEF(_DMyTest, _DMyTest);
    抱歉,没兴致去试,也不清楚为什么这样,也许是VC的一个小BUG(可能是用双接口实现的导致的)。
      

  6.   

    ActiveX控件依赖于容器,在创建之后需要和容器进行交互才可以正常运作,例如一些基于MFC的COleControl类的控件在设置控件站点之后才创建窗口。关于容器和控件交互的方法,可以参考MFC类的源代码。
    参考
    OleSetContainedObject
      

  7.   

    现在有没有成熟的使用#import调用MFC控件的方法?