C# 在windows 8.1上禁用触摸视觉反馈(以编程方式)[桌面应用程序]

C# 在windows 8.1上禁用触摸视觉反馈(以编程方式)[桌面应用程序],c#,winapi,windows-runtime,touch,windows-8.1,C#,Winapi,Windows Runtime,Touch,Windows 8.1,我有一个专门针对Win8.1的C#WPF应用程序(一个桌面应用程序,而不是metro) 我希望用户能够使用触摸注入,但我正在尝试禁用windows为点击手势、按住并拖动(如在桌面上选择多个文件)和其他手势(缩放、滚动等)创建的可视化反馈 在网上搜索了很长时间后,我发现了以下帖子: 所以我也试着这么做 我尝试了这个(将把我的Win32类放在最后) 还有: public void TryDisableWindowsVisualFeedback(IntPtr hWnd) { bool enab

我有一个专门针对Win8.1的C#WPF应用程序(一个桌面应用程序,而不是metro)

我希望用户能够使用触摸注入,但我正在尝试禁用windows为点击手势、按住并拖动(如在桌面上选择多个文件)和其他手势(缩放、滚动等)创建的可视化反馈

在网上搜索了很长时间后,我发现了以下帖子: 所以我也试着这么做

我尝试了这个(将把我的Win32类放在最后)

还有:

public void TryDisableWindowsVisualFeedback(IntPtr hWnd)
{
    bool enable = false;
    foreach (Win32.FEEDBACK_TYPE type in Enum.GetValues(typeof(Win32.FEEDBACK_TYPE)))
    {
        if (type == Win32.FEEDBACK_TYPE.FEEDBACK_MAX)
        {
            continue;
        }

        Logger.Debug(!Win32.SetWindowFeedbackSetting(hWnd, type, 0, 4, ref enable) 
               ? @"Failed to SetWindowFeedbackSetting for " + type
               : @"Successfuly returned from SetWindowFeedbackSetting for " + type);
    }
}
我从我的WPF应用程序中这样称呼它:

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    Window window = Window.GetWindow(this);
    var wih = new WindowInteropHelper(window);
    IntPtr hWnd = wih.Handle;
    TryDisableWindowsVisualFeedback(hWnd);
}
这是我的辅助Win32类:

internal class Win32
{
    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SystemParametersInfo(
        uint uiAction,
        uint uiParam,
        ref ulong pvParam,
        uint fWinIni
        );

    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")]
    public static extern bool SetWindowFeedbackSetting(
        IntPtr hwnd,
        FEEDBACK_TYPE feedback,
        uint dwFlags,
        uint size,
        [In] ref bool configuration
        );

}
上述非禁用圆形灰色点击视觉反馈,也未禁用按住并拖动时出现的白色小圆圈

我甚至尝试在博客中使用C#示例:

Windows.UI.Input.PointerVisualizationSettings.
GetForCurrentView().
IsContactFeedbackEnabled = false;
这段代码适用于metro应用程序,因此我尝试并获得了Windows名称空间,但在运行代码时,我得到了

"An unhandled exception of type 'System.Exception' occurred in MyProg.exe
WinRT information: Element not found.
Additional information: Element not found."
据我所知,桌面应用程序不支持
PointServiceSualizationSettings
,因此这种方式注定会失败

如果有人能帮我解决这个问题,请帮我


谢谢

您的TryDisableIndowsVisualFeedback方法似乎具有错误的pinvoke签名,因此您可能正在设置视觉反馈,而不是清除它。配置参数是BOOL*而不是BOOL*,BOOL是4字节整数。您可以使用以下属性修复此问题:

[In , MarshalAs(UnmanagedType.Bool)] ref bool configuration
您可以调用GetWindowFeedbackSetting来确认设置是否正确

对于右pinvoke和hWnd,SetWindowFeedbackSetting应该可以工作。我在本地应用程序中确认了这一点。WPF手柄接触有点奇怪。我不认为它会影响这一点,但我已经有好几年没有深入研究WPF了

对于其他方法,Windows.UI.Input类被记录为仅在Windows应用商店应用程序中工作,因此从桌面应用程序调用它们时可能会出现错误。在封面下,它们将进行与SetWindowFeedbackSetting相同的更改


使用SystemParametersInfo来影响全局UI是过分的:您不想通过引起全局问题来解决局部问题。也就是说,如果您触发更改通知,它可能会起作用。不过,使用SetWindowFeedbackSetting只针对您的窗口是一个更好的解决方案。

您的TryDisableIndowsVisualFeedback方法看起来有错误的pinvoke签名,因此您可能正在设置视觉反馈,而不是清除它。配置参数是BOOL*而不是BOOL*,BOOL是4字节整数。您可以使用以下属性修复此问题:

[In , MarshalAs(UnmanagedType.Bool)] ref bool configuration
您可以调用GetWindowFeedbackSetting来确认设置是否正确

对于右pinvoke和hWnd,SetWindowFeedbackSetting应该可以工作。我在本地应用程序中确认了这一点。WPF手柄接触有点奇怪。我不认为它会影响这一点,但我已经有好几年没有深入研究WPF了

对于其他方法,Windows.UI.Input类被记录为仅在Windows应用商店应用程序中工作,因此从桌面应用程序调用它们时可能会出现错误。在封面下,它们将进行与SetWindowFeedbackSetting相同的更改


使用SystemParametersInfo来影响全局UI是过分的:您不想通过引起全局问题来解决局部问题。也就是说,如果您触发更改通知,它可能会起作用。不过,使用SetWindowFeedbackSetting只针对您的窗口是一个更好的解决方案。

我也有类似的问题,我可以通过添加

Stylus.IsTapFeedbackEnabled = "False" to my root window.

我有一个类似的问题,我可以通过添加

Stylus.IsTapFeedbackEnabled = "False" to my root window.

我不知道这是否会解决OP的原始问题(甚至会产生影响),但我可以确认,我已经使用以下方法(几乎与OP建议的方法相同)成功禁用了我自己控件派生类的所有与触摸相关的视觉反馈,至少在我的Windows 10计算机上是这样的:

public class MyTouchControl: Control
{
    // ...a lot of other touch related stuff going on...

    enum FEEDBACK_TYPE
    {
        TOUCH_CONTACTVISUALIZATION = 1,
        PEN_BARRELVISUALIZATION = 2,
        PEN_TAP = 3,
        PEN_DOUBLETAP = 4,
        PEN_PRESSANDHOLD = 5,
        PEN_RIGHTTAP = 6,
        TOUCH_TAP = 7,
        TOUCH_DOUBLETAP = 8,
        TOUCH_PRESSANDHOLD = 9,
        TOUCH_RIGHTTAP = 10,
        GESTURE_PRESSANDTAP = 11
    }

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetWindowFeedbackSetting(IntPtr hWnd, FEEDBACK_TYPE feedback, int dwFlags, int size, ref int config);

    void disableAllTouchVisualFeedback()
    {
        int enable = 0;
        foreach (FEEDBACK_TYPE type in Enum.GetValues(typeof(FEEDBACK_TYPE)))
        {
            SetWindowFeedbackSetting(Handle, type, 0, 4, ref enable);
        }
    }

    protected override void OnHandleCreated(EventArgs e)
    {
        disableAllTouchVisualFeedback();
        base.OnHandleCreated(e);
    }
}

我不知道这是否会解决OP的原始问题(甚至会产生影响),但我可以确认,我已经使用以下方法(几乎与OP建议的方法相同)成功禁用了我自己控件派生类的所有与触摸相关的视觉反馈,至少在我的Windows 10计算机上是这样的:

public class MyTouchControl: Control
{
    // ...a lot of other touch related stuff going on...

    enum FEEDBACK_TYPE
    {
        TOUCH_CONTACTVISUALIZATION = 1,
        PEN_BARRELVISUALIZATION = 2,
        PEN_TAP = 3,
        PEN_DOUBLETAP = 4,
        PEN_PRESSANDHOLD = 5,
        PEN_RIGHTTAP = 6,
        TOUCH_TAP = 7,
        TOUCH_DOUBLETAP = 8,
        TOUCH_PRESSANDHOLD = 9,
        TOUCH_RIGHTTAP = 10,
        GESTURE_PRESSANDTAP = 11
    }

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetWindowFeedbackSetting(IntPtr hWnd, FEEDBACK_TYPE feedback, int dwFlags, int size, ref int config);

    void disableAllTouchVisualFeedback()
    {
        int enable = 0;
        foreach (FEEDBACK_TYPE type in Enum.GetValues(typeof(FEEDBACK_TYPE)))
        {
            SetWindowFeedbackSetting(Handle, type, 0, 4, ref enable);
        }
    }

    protected override void OnHandleCreated(EventArgs e)
    {
        disableAllTouchVisualFeedback();
        base.OnHandleCreated(e);
    }
}

感谢您的评论,我已经用
GetWindowFeedbackSetting
检查了更改,我发现在设置为false之前,我得到了一个假返回值(ref bool没有改变),在调用
SetWindowFeedbackSetting
和false之后,
GetWindowFeedbackSetting
输出了一个假值的布尔值。。。我会试试你的建议,但老实说,我对此表示怀疑。您介意发布您的本机应用程序吗?谢谢您的评论,我已经用
GetWindowFeedbackSetting
检查了更改,我发现在设置为false之前,我得到了一个false返回值(ref bool保持不变),并且在调用
SetWindowFeedbackSetting
后使用false,
GetWindowFeedbackSetting
使用假值输出布尔值。。。我会试试你的建议,但老实说,我对此表示怀疑。您介意发布您的本地应用程序吗?已经四年了:)不再使用此应用程序,但我希望我的代码能帮助您一些我几乎预料到的;-)但它确实帮了我很多。谢谢。已经四年了:)不再做这个了,但我希望我的代码能帮到你一些我几乎预料到的;-)但它确实帮了我很多。谢谢