gpt4 book ai didi

c++ - 如何通过 InvokeHelper 传递 HWND 以调用 .NET COM 对象?

转载 作者:太空宇宙 更新时间:2023-11-04 14:09:04 26 4
gpt4 key购买 nike

更新

我已经为原始问题制作了一个测试项目(我在下面移动了)。C#代码:

namespace TestManagedCom
{
[ComVisible(true)]
public class DummyObject
{
public void Method1(int value)
{
IntPtr hwnd = new IntPtr(value);
MessageBox.Show(string.Format("[Method1] value={0:X}, hwnd={1}", value, hwnd));
}

public void Method2(long value)
{
IntPtr hwnd = new IntPtr(value);
MessageBox.Show(string.Format("[Method2] value={0:X}, hwnd={1}", value, hwnd));
}
}
}

C++代码:

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);

它在目标为 x64 时运行良好。它打印:

[Method1] value=11223344, hwnd=287454020

[Method2] value=1122334455667788, hwnd=1234605616436508552

当目标是 x86 时,调用 Method2 会抛出异常。

First-chance exception at 0x76A2B727 in TestOleDispatcher.exe: Microsoft C++ exception: EEException at memory location 0x003FE3C4.

If there is a handler for this exception, the program may be safely continued.

我已经尝试了 long long__int64,错误显然是一样的。

它似乎无法在 x86 上正确编码 VTS_I8 参数。

原始问题

我在某些遗留代码中遇到问题,该代码调用 .NET 类中的方法,该类使用 COleDispatchDriver::InvokeHelper 表示 COM 对象。其中一个参数是窗口的句柄。

过去的 .NET 代码看起来像这样(简化):

[ComVisible(true)]
public class Sample
{
public void Method1(int hwndParent)
{
}
}

C++代码

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(因为它应该放在首位)。

[ComVisible(true)]
public class Sample
{
public void Method1(IntPtr hwndParent)
{
}
}

但现在的问题是如何使用 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 中为您提供窗口句柄。这将是实际的句柄,而不是指向句柄的指针。从您的代码来看,您似乎在期待一个指针来处理。我可以通过 long* hWnd 和 VTS_PI4 判断。

如果 COM 调用确实需要一个 INT_PTR(指向句柄的指针),您将必须存储传入的变量并获取它的地址才能传递。如果直接获取窗口句柄,则需要将VTS_PI4/VTS_PI8修改为VTS_I4/VTS_I8。

关于c++ - 如何通过 InvokeHelper 传递 HWND 以调用 .NET COM 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15644474/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com