Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用InvokeHelper传递HWND以调用.NET COM对象? 使现代化_C++_.net_Com_Marshalling_Ole - Fatal编程技术网

C++ 如何使用InvokeHelper传递HWND以调用.NET COM对象? 使现代化

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

我已经为原来的问题(我移到下面)做了一个测试项目。 C#代码:

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

和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