一开始做实验的时候程序用的Dialog Based的,对话框上放置了一些第三方的ActiveX控件,运行正常。后来根据需要程序改成了MDI,在CFormView上放置了同样的ActiveX控件(只是放置,没有其他关联操作),结果运行时提示“建立空文档失败”,查了相关的一些文档,在InitInstance里面加上了AfxEnableControlContainer(),错误没有了,但是却看不见控件。网上没有找到相关问题的解决方法。于是就用ClassWizard添加了该控件的一个成员变量,结果运行出错。跟踪进去发现是
CFormView::OnInitialUpdate();  ---------->
              ...
DDX_Control(pDX, IDC_ACTIVEX1, m_cmd);  ----------->void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl)
{
if (rControl.m_hWnd == NULL)    // not subclassed yet
{
ASSERT(!pDX->m_bSaveAndValidate);
HWND hWndCtrl = pDX->PrepareCtrl(nIDC); if (!rControl.SubclassWindow(hWndCtrl))
{
ASSERT(FALSE);      // possibly trying to subclass twice?
AfxThrowNotSupportedException();
}
#ifndef _AFX_NO_OCC_SUPPORT
else
{
// If the control has reparented itself (e.g., invisible control),
// make sure that the CWnd gets properly wired to its control site.
if (pDX->m_pDlgWnd->m_hWnd != ::GetParent(rControl.m_hWnd))
rControl.AttachControlSite(pDX->m_pDlgWnd);
}
#endif //!_AFX_NO_OCC_SUPPORT
}
}            ------------------>HWND CDataExchange::PrepareCtrl(int nIDC)
{
ASSERT(nIDC != 0);
ASSERT(nIDC != -1); // not allowed
HWND hWndCtrl;
m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
if (hWndCtrl == NULL)
{
TRACE1("Error: no data exchange control with ID 0x%04X.\n", nIDC);
ASSERT(FALSE);
AfxThrowNotSupportedException();
}
m_hWndLastControl = hWndCtrl;
m_bEditLastControl = FALSE; // not an edit item by default
ASSERT(hWndCtrl != NULL);   // never return NULL handle
return hWndCtrl;
}          ----------------------------->void COleControlContainer::GetDlgItem(int nID, HWND* phWnd) const
{
// first, look for a non-OLE control
HWND hWnd = ::GetDlgItem(m_pWnd->GetSafeHwnd(), nID);
if (hWnd == NULL)
{
// now, look for an OLE control
COleControlSite* pSite = FindItem(nID);
if (pSite != NULL)
hWnd = pSite->m_hWnd;
} *phWnd = hWnd;
}       ------------------------->COleControlSite* COleControlContainer::FindItem(UINT nID) const
{
POSITION pos = m_siteMap.GetStartPosition();返回pos=NULL
while (pos != NULL)
{
HWND hWnd;
COleControlSite* pSite;
m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
if (pSite->GetID() == nID)
return pSite;
}
return NULL;
}跟踪到最后m_siteMap.GetStartPosition()返回pos=NULL,导致这个错误。请过路高手指点怎么会容器中没有控件!

解决方案 »

  1.   

    没有人帮忙吗?再跟踪下去,发现控件不显示和DDX出错都是在这个函数里面出错:HRESULT COleControlSite::CreateControl(CWnd* pWndCtrl, REFCLSID clsid,
    LPCTSTR lpszWindowName, DWORD dwStyle, const POINT* ppt, const SIZE* psize,
       UINT nID, CFile* pPersist, BOOL bStorage, BSTR bstrLicKey)
    {
    HRESULT hr = E_FAIL;
    m_hWnd = NULL;
       CSize size; // Connect the OLE Control with its proxy CWnd object
    if (pWndCtrl != NULL)
    {
    ASSERT(pWndCtrl->m_pCtrlSite == NULL);
    m_pWndCtrl = pWndCtrl;
    pWndCtrl->m_pCtrlSite = this;
    } // Initialize OLE, if necessary
    _AFX_THREAD_STATE* pState = AfxGetThreadState();
    if (!pState->m_bNeedTerm && !AfxOleInit())
    return hr; if (SUCCEEDED(hr = CreateOrLoad(clsid, pPersist, bStorage, bstrLicKey)))
    {
    ASSERT(m_pObject != NULL);
    m_nID = nID; if (psize == NULL)
    {
    // If psize is NULL, ask the object how big it wants to be.
    CClientDC dc(NULL); m_pObject->GetExtent(DVASPECT_CONTENT, &size);
    dc.HIMETRICtoDP(&size);
    m_rect = CRect(*ppt, size);
    }
    else
    {
    m_rect = CRect(*ppt, *psize);
    } m_dwStyleMask = WS_GROUP | WS_TABSTOP; if (m_dwMiscStatus & OLEMISC_ACTSLIKEBUTTON)
    m_dwStyleMask |= BS_DEFPUSHBUTTON; if (m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)
    dwStyle &= ~WS_VISIBLE; m_dwStyle = dwStyle & m_dwStyleMask; // If control wasn't quick-activated, then connect sinks now.
    if (hr != S_QUICKACTIVATED)
    {
    m_dwEventSink = ConnectSink(m_iidEvents, &m_xEventSink);
    m_dwPropNotifySink = ConnectSink(IID_IPropertyNotifySink,
    &m_xPropertyNotifySink);
    }
    m_dwNotifyDBEvents = ConnectSink(IID_INotifyDBEvents, &m_xNotifyDBEvents); // Now that the object has been created, attempt to
    // in-place activate it. SetExtent(); if (SUCCEEDED(hr = m_pObject->QueryInterface(IID_IOleInPlaceObject,
    (LPVOID*)&m_pInPlaceObject)))
    {
    if (dwStyle & WS_VISIBLE)
    {
    // control is visible: just activate it
    hr = DoVerb(OLEIVERB_INPLACEACTIVATE);
    }
    else
    {
    // control is not visible: activate off-screen, hide, then move
    m_rect.OffsetRect(-32000, -32000);
    if (SUCCEEDED(hr = DoVerb(OLEIVERB_INPLACEACTIVATE)) &&
    SUCCEEDED(hr = DoVerb(OLEIVERB_HIDE)))
    {
    m_rect.OffsetRect(32000, 32000);
    hr = m_pInPlaceObject->SetObjectRects(m_rect, m_rect);
    }
    }
    }
    else
    {
    TRACE1("IOleInPlaceObject not supported on OLE control (dialog ID %d).\n", nID);
    TRACE1(">>> Result code: 0x%08lx\n", hr);
    } if (SUCCEEDED(hr))
    GetControlInfo(); // if QueryInterface or activation failed, cleanup everything
    if (FAILED(hr))
    {
             ................上面红色的DoVerb语句返回hr=0x8001010D,后面的if (SUCCEEDED(hr))没有通过!请问是怎么回事啊?
      

  2.   

    AfxOleInit();
    CoInitialize(NULL);
      

  3.   

    To sjdev:加入AfxOleInit()之后能够显示ActiveX控件了,但原来的功能却不能用了。因为程序里原来调用了AfxOleInit2()这个函数(是别人写的),以为里面调用了AfxOleInt(),实际没有。这段代码如下:
    BOOL AFXAPI AfxOleInit2()
    {
    _AFX_THREAD_STATE* pState = AfxGetThreadState();
    ASSERT(!pState->m_bNeedTerm);    // calling it twice? // Special case DLL context to assume that the calling app initializes OLE.
    // For DLLs where this is not the case, those DLLs will need to initialize
    // OLE for themselves via OleInitialize.  This is done since MFC cannot provide
    // automatic uninitialize for DLLs because it is not valid to shutdown OLE
    // during a DLL_PROCESS_DETACH.
    if (afxContextIsDLL)
    {
    pState->m_bNeedTerm = -1;  // -1 is a special flag
    return TRUE;
    } // first, initialize OLE
    //SCODE sc = ::OleInitialize(NULL);
    SCODE sc = ::CoInitializeEx(NULL,COINIT_MULTITHREADED);
    //SCODE sc = ::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);  if (FAILED(sc))
    {
    // warn about non-NULL success codes
    TRACE1("Warning: OleInitialize returned scode = %s.\n",
    AfxGetFullScodeString(sc));
    goto InitFailed;
    }
    // termination required when OleInitialize does not fail
    pState->m_bNeedTerm = TRUE; // hook idle time and exit time for required OLE cleanup
    CWinThread* pThread; pThread = AfxGetThread();
    pThread->m_lpfnOleTermOrFreeLib = AfxOleTermOrFreeLib; // allocate and initialize default message filter
    if (pThread->m_pMessageFilter == NULL)
    {
    pThread->m_pMessageFilter = new COleMessageFilter;
    ASSERT(AfxOleGetMessageFilter() != NULL);
    AfxOleGetMessageFilter()->Register();
    }
    return TRUE;InitFailed:
    AfxOleTerm();
    return FALSE;
    }没看懂是派啥用场的,能再帮忙看看吗?
      

  4.   

    嗬嗬,看了一下,AfxOleInit2()就是把MFC的AfxOleInit()函数里面的
    //SCODE sc = ::OleInitialize(NULL); 
    换成了
    SCODE sc = ::CoInitializeEx(NULL,COINIT_MULTITHREADED); 我把原来调用的AfxOleInit2换成标准的AfxOleInit控件就能显示了,但原来的功能就不能实现,而在后面另外加上CoInitializeEx(NULL,COINIT_MULTITHREADED)却出错。我是菜鸟,帮忙看看吧
      

  5.   

    To:sjdev  就像你说的,用了CoInitialize(NULL)就行了,但用::CoInitializeEx(NULL,COINIT_MULTITHREADED)却出错。能解释一下吗?我是想搞懂原因,分我一定给,再加分也行:)