Отключить сенсорную визуальную обратную связь в Windows 8.1 (программно) [Настольное приложение]

1

У меня есть приложение С# WPF, предназначенное специально для Win8.1 (настольное приложение, НЕ метро).

Я хочу, чтобы пользователи имели возможность использовать сенсорные инъекции, но я пытаюсь отключить обратную визуализацию, которую создают окна для жестов Tap. Нажмите Hold и Drag (например, выбор нескольких файлов на рабочем столе) и другие жесты (масштабирование прокрутки и т.д.).

После поиска в Интернете в течение долгого времени я нашел это сообщение: Как отключить визуализацию контактов Windows 8 для моего приложения? Поэтому я попытался сделать то же самое...

Я попробовал это (поместит мой класс Win32 в конец)

public void DisableGestureVisualization()
{
    const int SPI_SETCONTACTVISUALIZATION = 0x2019;
    const int SPI_SETGESTUREVISUALIZATION = 0x201B;
    ulong gv = 0;
    Logger.Debug(!Win32.SystemParametersInfo(SPI_SETGESTUREVISUALIZATION, 0, ref gv, 0)
        ? @"Failed SystemParametersInfo SPI_SETGESTUREVISUALIZATION"
        : @"Successfuly returned from SystemParametersInfo SPI_SETGESTUREVISUALIZATION");

    Logger.Debug(!Win32.SystemParametersInfo(SPI_SETCONTACTVISUALIZATION, 0, ref gv, 0)
        ? @"Failed SystemParametersInfo SPI_SETCONTACTVISUALIZATION"
        : @"Successfuly returned from SystemParametersInfo SPI_SETCONTACTVISUALIZATION");
}

А также это:

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

}

Non из вышеперечисленного отключил визуальную обратную связь круглого серого крана или не отключил маленький белый круг, который появляется при удержании и перетаскивании.

Я даже попытался использовать пример С# в блоге:

Windows.UI.Input.PointerVisualizationSettings.
GetForCurrentView().
IsContactFeedbackEnabled = false;

Этот код работает для приложения метро, поэтому я попробовал эту публикацию SO и получил пространство имен Windows, но при запуске кода, который я получаю

"An unhandled exception of type 'System.Exception' occurred in MyProg.exe
WinRT information: Element not found.
Additional information: Element not found."

Из того, что я мог понять, PointerVisualizationSettings не поддерживается из настольного приложения, поэтому этот способ обречен...

Если кто-нибудь может мне помочь в этом вопросе, пожалуйста.

благодаря

Теги:
winapi
touch
windows-runtime
windows-8.1

3 ответа

3

У меня была аналогичная проблема, и я смог удалить обратную реакцию с помощью жестов, добавив

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

Ваш метод TryDisableWindowsVisualFeedback выглядит так, как будто у него неправильная сигнатура pinvoke, поэтому вы можете настраивать визуальную обратную связь, а не очищать ее. Аргумент конфигурации - это BOOL *, а не bool *, а BOOL - 4 байта. Вы можете исправить это с помощью атрибута MarshalAs:

[In , MarshalAs(UnmanagedType.Bool)] ref bool configuration

Вы можете вызвать GetWindowFeedbackSetting, чтобы подтвердить, что он был установлен правильно.

При правильном pinvoke и hWnd, SetWindowFeedbackSetting должен работать. Я подтвердил, что это делает для меня в родном приложении. Рукоятки WPF касаются немного странно. Я бы не ожидал, что это повлияет на это, но я не смотрел на WPF в глубину в течение нескольких лет.

Для ваших других методов классы Windows.UI.Input документируются для работы только в приложениях Windows Store, поэтому ожидаются ошибки, вызывающие их из настольного приложения. Под обложками они будут делать те же изменения, что и SetWindowFeedbackSetting.

Использование SystemParametersInfo для воздействия на глобальный пользовательский интерфейс является чрезмерным: вы не хотите решать локальную проблему, вызывая глобальную. Тем не менее, это, вероятно, будет работать, если вы стреляете уведомлениями об изменениях. Однако использование SetWindowFeedbackSetting для целевого только вашего окна - гораздо лучшее решение.

  • 0
    Спасибо за ваш комментарий, я уже проверил изменение с помощью GetWindowFeedbackSetting и вижу, что перед установкой в false я получаю ложное возвращаемое значение (и ref bool не изменяется) и после вызова SetWindowFeedbackSetting со значением false, GetWindowFeedbackSetting выводит логическое значение с ложным значением ... Я попробую ваше предложение, но я скептически отношусь к честности. Не могли бы вы опубликовать свое родное приложение?
0

Я не знаю, разрешит ли это оригинальную проблему OP (или даже изменит ли ее значение), но я могу подтвердить, что я успешно отключил все визуальные обратные связи, связанные с касанием, для моего собственного класса, производного от Control, выборочно следующим методом (почти как предложенный ОП) - по крайней мере, на моем компьютере с 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);
    }
}
  • 0
    Прошло 4 года с тех пор :) больше не работаю над этим, но я надеюсь, что мой код помог вам как-то
  • 1
    Я почти ожидал этого ;-) Но это мне очень помогло. Благодарю.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню