当我在Delphi 7中创建基于TPanel的ActiveX控件(没有添加代码),我可以将其添加到MFC C ++应用程序中并使其正常运行。
当我使用完全相同的代码并在Delphi XE4(和XE2)中编译它时,MFC会抛出一个断言。我确认唯一的更改是在dcu、ocx和res文件中。
断言发生在occsite.cpp中的
当我使用完全相同的代码并在Delphi XE4(和XE2)中编译它时,MFC会抛出一个断言。我确认唯一的更改是在dcu、ocx和res文件中。
断言发生在occsite.cpp中的
ASSERT(wFlags == DISPATCH_METHOD);
处(我包含了此文件的源代码)。STDMETHODIMP COleControlSite::XEventSink::Invoke(
DISPID dispid, REFIID, LCID, unsigned short wFlags,
DISPPARAMS* pDispParams, VARIANT* pvarResult,
EXCEPINFO* pExcepInfo, unsigned int* puArgError)
{
UNUSED(wFlags);
METHOD_PROLOGUE_EX(COleControlSite, EventSink)
ASSERT(pThis->m_pCtrlCont != NULL);
ASSERT(pThis->m_pCtrlCont->m_pWnd != NULL);
ASSERT(wFlags == DISPATCH_METHOD);
AFX_EVENT event(AFX_EVENT::event, dispid, pDispParams, pExcepInfo,
puArgError);
pThis->OnEvent(&event);
if (pvarResult != NULL)
::VariantClear(pvarResult);
return event.m_hResult;
}
wFlags的值为DISPATCH_METHOD | DISPATCHPROPERTYGET。
之后似乎一切正常(如果你从XE4开始,鼠标事件会导致类似的问题,但是D7不包括它们)。
我在Visual Studio 2010和Visual Studio 2012中都尝试过。在MFC中,我创建了一个新的MFC对话框应用程序,右键单击并选择添加ActiveX控件。我对MFC相对较新,所以可能做错了。
宿主系统是Win 7 x64系统。
我不能在代码中留下断言,真的希望能正确地使其工作,这样我将来可以重用大量的Delphi代码。
有什么想法或者有人能指点我一个比在键盘上敲头更好的方向吗?
更新:2013.09.18
Remy的答案是正确的,但这里还有更多信息。
从XE4开始,似乎主要问题是发送回控件宿主的事件(即OnClickEvent、OnMouseEnter、OnMouseLeave、OnConstrainedResize、OnCanResize或OnResizeEvent)。
我找到了3种可能的解决方案(如果我找到了更多,我会再次更新):
- 注释掉调用这些事件的代码(我没有说它们是好的解决方案)。
- 注释掉ComObjs.DispatchInvoke中导致其设置的行。
- 修改ComObjs以具有备用的DispatchInvoke和DispCallByID
- 备用的DispCallID需要调用备用的DispatchInvoke。
- 备用的DispatchInvoke需要删除更改标志的代码
- 在事件使用时,全局变量DispCallByIDProc需要设置为备用的DispCallByID过程。
- DispCallByIDProc在设置为替代方法后需要被设置回来(我将其作为备用DispCallByID的第一行执行)。
我使用类似以下内容来包围事件被调用的位置:
FEvents <> nil then
try
SetDispatchByCallID(True);
FEvents.OnClick;
finally
SetDispatchByCallID(False);
end;