C++ 如何使用InvokeHelper传递HWND以调用.NET COM对象? 使现代化
我已经为原来的问题(我移到下面)做了一个测试项目。 C#代码: C++代码:C++ 如何使用InvokeHelper传递HWND以调用.NET COM对象? 使现代化,c++,.net,com,marshalling,ole,C++,.net,Com,Marshalling,Ole,我已经为原来的问题(我移到下面)做了一个测试项目。 C#代码: C++代码: class CDispatchWrapper : public COleDispatchDriver { public: CDispatchWrapper(){} CDispatchWrapper(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {} CDispatchWrapper(const CDispatchWrapper& d
class CDispatchWrapper : public COleDispatchDriver
{
public:
CDispatchWrapper(){}
CDispatchWrapper(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
CDispatchWrapper(const CDispatchWrapper& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}
void CallMethod(DISPID dwDispID, int value)
{
static BYTE parms[] = VTS_I4;
InvokeHelper(dwDispID, DISPATCH_METHOD, VT_EMPTY, NULL, parms, value);
}
void CallMethod(DISPID dwDispID, long long value)
{
static BYTE parms[] = VTS_I8;
InvokeHelper(dwDispID, DISPATCH_METHOD, VT_EMPTY, NULL, parms, value);
};
};
template <typename T>
void Execute(const CString& progId, const CString& methodName, T value)
{
LPDISPATCH lpEventComponent = NULL;
_com_ptr_t<_com_IIID<IDispatch, &IID_IDispatch> > pCreateComp;
HRESULT hr = pCreateComp.CreateInstance(progId);
if(SUCCEEDED(hr) && pCreateComp != NULL)
{
hr = pCreateComp.QueryInterface(IID_IDispatch, (void**)&lpEventComponent);
if(SUCCEEDED(hr))
{
USES_CONVERSION;
DISPID dwFunctionID = 0;
OLECHAR FAR *szFunc = T2OLE(const_cast<LPTSTR>(methodName.GetString()));
hr = lpEventComponent->GetIDsOfNames(IID_NULL, &szFunc, 1, LOCALE_SYSTEM_DEFAULT, &dwFunctionID);
if(SUCCEEDED(hr) && dwFunctionID != -1)
{
lpEventComponent->AddRef(); // released by the dispatch driver
CDispatchWrapper wrapper(lpEventComponent);
wrapper.CallMethod(dwFunctionID, value);
}
}
}
}
Execute<int>(_T("TestManagedCom.DummyObject"), _T("Method1"), 0x11223344);
Execute<long long>(_T("TestManagedCom.DummyObject"), _T("Method2"), 0x1122334455667788LL);
和C++代码< /P>
class CSendEventWrapper : public COleDispatchDriver
{
public:
void CallMethod(DISPID dwDispID, long* hwnd)
{
static BYTE parms[] = VTS_PI4;
InvokeHelper(dwDispID, DISPATCH_METHOD, VT_EMPTY, NULL, parms, hwnd);
}
};
HWND hWnd = ...;
long lval = (long)hWnd;
o.CallMethod(dispId, &lval); // snippet for calling the method
当C++应用程序只有32位时,这就行了。但在64位版本上,这是不正确的,因为HWND
是64位的,long
只是32位的,所以会丢失数据
因此,我开始将.NET代码改为使用IntPtr
,而不是int
(本来应该是这样的)
但现在的问题是如何使用InvokeHelper
调用它。我试过这样做:
void CallMethod(DISPID dwDispID, INT_PTR hwnd)
{
#ifdef _WIN64
static BYTE parms[] = VTS_PI8;
#else
static BYTE parms[] = VTS_PI4;
#endif
InvokeHelper(dwDispID, DISPATCH_METHOD, VT_EMPTY, NULL, parms, hwnd);
}
HWND hWnd = ...;
INT_PTR lval = (INT_PTR)hWnd; // 32- or 64-bit depending on the platform
o.CallMethod(dispId, &lval); // snippet for calling the method
但是,这现在会导致一个异常,即参数的格式不正确IntPtr
应为32位或64位,具体取决于进程是32位还是64位。我不知道怎么了
对于如何使用
InvokeHelper
正确传递32位和64位版本的HWND,请提供任何帮助。(不,我不能代替使用COleDispatchDriver
)。看起来您的参数类型不匹配。从c#获取句柄通常会在IntPtr中提供窗口句柄。这将是实际的句柄,而不是指向句柄的指针。从您的代码来看,您似乎希望处理一个指针。我可以通过长时间的观察和VTS_PI4来判断
如果COM调用确实需要INT_PTR(指向句柄的指针),则必须存储传入的变量并获取要传递的地址。如果它直接使用窗口句柄,则需要将VTS_PI4/VTS_PI8修改为VTS_I4/VTS_I8。异常在哪里?任何异常详细信息?您似乎有64位的VTS_PI4和32位的VTS_PI8。你确定那是对的吗?说得好;只是我在浏览器中编辑代码时出错了。关于这一点,实际代码是正确的。MFC不支持VT_INT_PTR。只要保持VTS_PI8的一致性,托管代码就可以以任意比特转换为IntPtr。
class CSendEventWrapper : public COleDispatchDriver
{
public:
void CallMethod(DISPID dwDispID, long* hwnd)
{
static BYTE parms[] = VTS_PI4;
InvokeHelper(dwDispID, DISPATCH_METHOD, VT_EMPTY, NULL, parms, hwnd);
}
};
HWND hWnd = ...;
long lval = (long)hWnd;
o.CallMethod(dispId, &lval); // snippet for calling the method
[ComVisible(true)]
public class Sample
{
public void Method1(IntPtr hwndParent)
{
}
}
void CallMethod(DISPID dwDispID, INT_PTR hwnd)
{
#ifdef _WIN64
static BYTE parms[] = VTS_PI8;
#else
static BYTE parms[] = VTS_PI4;
#endif
InvokeHelper(dwDispID, DISPATCH_METHOD, VT_EMPTY, NULL, parms, hwnd);
}
HWND hWnd = ...;
INT_PTR lval = (INT_PTR)hWnd; // 32- or 64-bit depending on the platform
o.CallMethod(dispId, &lval); // snippet for calling the method