У меня есть приложение С# 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
не поддерживается из настольного приложения, поэтому этот способ обречен...
Если кто-нибудь может мне помочь в этом вопросе, пожалуйста.
благодаря
У меня была аналогичная проблема, и я смог удалить обратную реакцию с помощью жестов, добавив
Stylus.IsTapFeedbackEnabled = "False" to my root window.
Ваш метод 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 для целевого только вашего окна - гораздо лучшее решение.
Я не знаю, разрешит ли это оригинальную проблему 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);
}
}
GetWindowFeedbackSetting
и вижу, что перед установкой в false я получаю ложное возвращаемое значение (и ref bool не изменяется) и после вызоваSetWindowFeedbackSetting
со значением false,GetWindowFeedbackSetting
выводит логическое значение с ложным значением ... Я попробую ваше предложение, но я скептически отношусь к честности. Не могли бы вы опубликовать свое родное приложение?