一开始做实验的时候程序用的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,导致这个错误。请过路高手指点怎么会容器中没有控件!
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,导致这个错误。请过路高手指点怎么会容器中没有控件!
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))没有通过!请问是怎么回事啊?
CoInitialize(NULL);
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;
}没看懂是派啥用场的,能再帮忙看看吗?
//SCODE sc = ::OleInitialize(NULL);
换成了
SCODE sc = ::CoInitializeEx(NULL,COINIT_MULTITHREADED); 我把原来调用的AfxOleInit2换成标准的AfxOleInit控件就能显示了,但原来的功能就不能实现,而在后面另外加上CoInitializeEx(NULL,COINIT_MULTITHREADED)却出错。我是菜鸟,帮忙看看吧