【问题标题】:PInvoke WPF HWND and const void*PInvoke WPF HWND 和 const void*
【发布时间】:2014-12-18 07:15:30
【问题描述】:

我需要在我的 WPF 应用程序中使用以下 C++ 函数:

/****************************************
* BOOL WINAPI SetWindowFeedbackSetting(
*  _In_      HWND hwnd,
*  _In_      FEEDBACK_TYPE feedback,
*  _In_      DWORD dwFlags,
*  _In_      UINT32 size,
*  _In_opt_  const VOID *configuration
*);
*****************************************/

但我不确定如何编组它以及如何 PInvoke 它。这是我目前所拥有的:

public enum FEEDBACK_TYPE : uint { 
    FEEDBACK_TOUCH_CONTACTVISUALIZATION  = 1,
    FEEDBACK_PEN_BARRELVISUALIZATION     = 2,
    FEEDBACK_PEN_TAP                     = 3,
    FEEDBACK_PEN_DOUBLETAP               = 4,
    FEEDBACK_PEN_PRESSANDHOLD            = 5,
    FEEDBACK_PEN_RIGHTTAP                = 6,
    FEEDBACK_TOUCH_TAP                   = 7,
    FEEDBACK_TOUCH_DOUBLETAP             = 8,
    FEEDBACK_TOUCH_PRESSANDHOLD          = 9,
    FEEDBACK_TOUCH_RIGHTTAP              = 10,
    FEEDBACK_GESTURE_PRESSANDTAP         = 11,
    FEEDBACK_MAX                         = 0xFFFFFFFF
}

[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)] // (1)
public static extern bool SetWindowFeedbackSetting(
    [In] IntPtr hwnd,
    [In] FEEDBACK_TYPE feedback,
    [In] uint dwFlags,
    [In] uint size,           // (2)
    [In, Optional] IntPtr configuration // (3)
 );

首先,(1),(2),(3) 正确吗?

其次,如果我想根据这个C++函数调用PInvoke这个函数:

BOOL fEnabled = FALSE;
BOOL res = SetWindowFeedbackSetting(
              hwnd,
              FEEDBACK_TOUCH_CONTACTVISUALIZATION,
              0,
              sizeof(fEnabled),
              &fEnabled
           );

发送 HWND 和布尔值的方式是什么?

我问这个问题是为了更好地理解 pinvoke\Marshal 机制,而且因为我尝试的方式不起作用。

谢谢

【问题讨论】:

标签: c# c++ wpf pinvoke


【解决方案1】:

您的翻译是准确的。但就个人而言,为了方便起见,我会为您需要使用的每种类型制作一个重载。对于布尔值:

[DllImport("user32.dll"])
public static extern bool SetWindowFeedbackSetting(
    IntPtr hwnd,
    FEEDBACK_TYPE feedback,
    uint dwFlags,
    uint size,          
    [In] ref bool configuration 
);

我删除了不需要的属性,因为它们重述了默认值。

记住 Win32 BOOL 类型,C# bool 的默认编组选项是 4 字节类型。所以你必须传递 4 作为大小。

请参阅此问题以了解如何获取 WPF 窗口的窗口句柄:How to get the hWnd of Window instance?

【讨论】:

  • 所以使用这个 PInvoke 我可以发送一个 .NET bool 而无需任何编组?编辑:您刚刚编辑了答案:)
  • @Hans 谢谢。好点子。完毕。编组的 ShaZiv 仍然完成,只是在幕后为您完成。
【解决方案2】:

据我记忆,P/Invoke 机制在传递/返回 .NET 的布尔值方面存在问题。我会这样做:

[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)] // (1)
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowFeedbackSetting(
    [In] IntPtr hwnd,
    [In] FEEDBACK_TYPE feedback,
    [In] uint dwFlags,
    [In] uint size,           // (2)
    [In, Optional] IntPtr configuration // (3)
);

然后,您必须在 WPF 中获取当前窗口的 HWND。这个问题:How to get the hWnd of Window instance? 应该有助于解决这个问题。

为了您的方便:

Window window = Window.GetWindow(this);
var wih = new WindowInteropHelper(window);
IntPtr hWnd = wih.Handle;

(归功于 Drahcir)

最后,要获取布尔值的地址,我会执行以下操作:

int myBool; // Win32's BOOL is actually an 4-byte integral number, 0 or non-zero
GCHandle handle = GCHandle.Alloc(myBool, GCHandleType.Pinned);
try
{
    IntPtr ptr = handle.AddrOfPinnedObject();

    // use ptr
}
finally
{
    handle.Free();
}

【讨论】:

  • @DavidHeffernan 这么认为 :) 已修复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多