在 Windows 8 下,触摸 WPF 按钮有时不会调用单击处理程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28441538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Touching a WPF button does sometimes not invoke the click handler under Windows 8
提问by Michael Podlejska
"When the application window does NOT have the focus, sometimes the click handler is not called on button-touch."
“当应用程序窗口没有焦点时,有时不会在按钮触摸时调用点击处理程序。”
System:
系统:
Windows 8.1 with a multi-touch input device.
带有多点触控输入设备的 Windows 8.1。
Software:
软件:
A simple WPF 4.5.2 application with just one button that logs if the click handler is called (just create a new project and add a button with a click handler to the MainWindow).
一个简单的 WPF 4.5.2 应用程序,只有一个按钮,用于记录是否调用了单击处理程序(只需创建一个新项目并将带有单击处理程序的按钮添加到 MainWindow)。
Phenomenon:
现象:
Normally when touching the button its click handler is called. But when the application window does NOT have the focus, sometimes the click handler is not called on button-touch(although the button color changes to blue). When the application window has already the focus, touching the button works all the time. This happens only sometimes but occurs on various systems with different touch hardware (all windows 8.1). I never experienced it on windows 7. With the mouse it works regardless if the window is focused or not.
通常当触摸按钮时,它的点击处理程序被调用。但是当应用程序窗口没有焦点时,有时单击处理程序不会在按钮触摸时调用(尽管按钮颜色变为蓝色)。当应用程序窗口已经获得焦点时,触摸按钮一直有效。这只是偶尔发生,但会发生在具有不同触摸硬件的各种系统上(所有 Windows 8.1)。我从未在 Windows 7 上体验过。使用鼠标,无论窗口是否聚焦,它都可以工作。
(Happens in release and debug mode, with and without debugger attached)
(在发布和调试模式下发生,有和没有连接调试器)
Testing:
测试:
I checked the various touch settings in windows and played with it. I also re-calibrating the touch -> no difference.
我检查了 Windows 中的各种触摸设置并进行了操作。我还重新校准了触摸 -> 没有区别。
When checking the WPF button mouse and touch events, then in the error case the last received event is PreviewMouseUp but no Click!
检查 WPF 按钮鼠标和触摸事件时,在错误情况下,最后收到的事件是 PreviewMouseUp 但没有 Click!
When I look at the received window messages (spy++) I get the following (WM_IME_SETCONTEXT, WM_GETTEXT, WM_NCHITTEST, WM_GETOBJECT removed for a better overview):
当我查看收到的窗口消息 (spy++) 时,我得到以下信息(WM_IME_SETCONTEXT、WM_GETTEXT、WM_NCHITTEST、WM_GETOBJECT 被删除以获得更好的概览):
Click was received:
收到点击:
R WM_POINTERACTIVATE pmsd->lResult:FFFFFFFFFFFFFFFF
S WM_MOUSEACTIVATE hwndTopLevel:000503F8 nHittest:HTCLIENT uMsg:WM_POINTERDOWN
R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE
S WM_WINDOWPOSCHANGING lpwp:000000E9E3D9E410
R WM_WINDOWPOSCHANGING
S WM_WINDOWPOSCHANGED lpwp:000000E9E3D9E410
R WM_WINDOWPOSCHANGED
S WM_ACTIVATEAPP fActive:True dwThreadID:00000000
R WM_ACTIVATEAPP
S WM_NCACTIVATE fActive:True
R WM_NCACTIVATE
S WM_ACTIVATE fActive:WA_ACTIVE fMinimized:False hwndPrevious:(null)
S WM_IME_NOTIFY dwCommand:IMN_OPENSTATUSWINDOW dwCommand:00000002 dwData:00000000
R WM_IME_NOTIFY
S WM_SETFOCUS hwndLoseFocus:(null)
R WM_SETFOCUS
R WM_ACTIVATE
S message:0x02CC [Unknown] wParam:00000000 lParam:00C50BA8
R message:0x02CC [Unknown] lResult:00000100
P WM_POINTERENTER wPointerID:0099 wFlags:6017
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_LBUTTONDOWN
R WM_SETCURSOR fHaltProcessing:False
P WM_LBUTTONDOWN fwKeys:MK_LBUTTON xPos:145 yPos:62
R WM_POINTERCAPTURECHANGED
P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:145 yPos:62
P WM_POINTERLEAVE wPointerID:0099 wFlags:6000
P WM_LBUTTONUP fwKeys:0000 xPos:145 yPos:62
P WM_MOUSEMOVE fwKeys:0000 xPos:145 yPos:62
S WM_CAPTURECHANGED hwndNewCapture:000503F8
R WM_CAPTURECHANGED
S WM_CAPTURECHANGED hwndNewCapture:00000000
R WM_CAPTURECHANGED
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
R WM_SETCURSOR fHaltProcessing:False
P WM_MOUSEMOVE fwKeys:0000 xPos:145 yPos:62
Click NOT received
点击未收到
S message:0x02CC [Unknown] wParam:00000000 lParam:00AE0BA9
R message:0x02CC [Unknown] lResult:00000100
R WM_POINTERACTIVATE pmsd->lResult:FFFFFFFFFFFFFFFF
S WM_MOUSEACTIVATE hwndTopLevel:000503F8 nHittest:HTCLIENT uMsg:WM_POINTERDOWN
R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE
S WM_WINDOWPOSCHANGING lpwp:000000E9E3D9E410
R WM_WINDOWPOSCHANGING
S WM_WINDOWPOSCHANGED lpwp:000000E9E3D9E410
R WM_WINDOWPOSCHANGED
S WM_ACTIVATEAPP fActive:True dwThreadID:00000000
R WM_ACTIVATEAPP
S WM_NCACTIVATE fActive:True
R WM_NCACTIVATE
S WM_ACTIVATE fActive:WA_ACTIVE fMinimized:False hwndPrevious:(null)
S WM_IME_NOTIFY dwCommand:IMN_OPENSTATUSWINDOW dwCommand:00000002 dwData:00000000
R WM_IME_NOTIFY
S WM_SETFOCUS hwndLoseFocus:(null)
R WM_SETFOCUS
R WM_ACTIVATE
P WM_POINTERENTER wPointerID:0090 wFlags:6017
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_LBUTTONDOWN
R WM_SETCURSOR fHaltProcessing:False
P WM_LBUTTONDOWN fwKeys:MK_LBUTTON xPos:147 yPos:39
R WM_POINTERCAPTURECHANGED
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
R WM_SETCURSOR fHaltProcessing:False
P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:147 yPos:39
P WM_POINTERLEAVE wPointerID:0090 wFlags:6000
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_LBUTTONUP
R WM_SETCURSOR fHaltProcessing:False
P WM_LBUTTONUP fwKeys:0000 xPos:147 yPos:39
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
R WM_SETCURSOR fHaltProcessing:False
P WM_MOUSEMOVE fwKeys:0000 xPos:147 yPos:39
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
R WM_SETCURSOR fHaltProcessing:False
P WM_MOUSEMOVE fwKeys:0000 xPos:147 yPos:39
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
R WM_SETCURSOR fHaltProcessing:False
P WM_MOUSEMOVE fwKeys:0000 xPos:147 yPos:39
In the error there are additional lines
在错误中有额外的行
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_LBUTTONUP
R WM_SETCURSOR fHaltProcessing:False
before WM_LBUTTONUP. But I don't know if this matter.
在 WM_LBUTTONUP 之前。不过不知道有没有关系。
I already tried to debug the .net code to see which condition causes to not call the Click handler but I soon got lost in the System.Windows.Input.InputManager and the PromoteMainToMouse() function of System.Windows.Input.StylusLogic.
我已经尝试调试 .net 代码以查看哪些条件导致不调用 Click 处理程序,但很快我就迷失在 System.Windows.Input.InputManager 和 System.Windows.Input.StylusLogic 的提升 MainToMouse() 函数中。
I'm really running out of ideas what to check. So it would be great if someone could give me advice what else to test or where to set breakpoints in .net to find the root-cause. Or even better find a solution/workaround.
我真的没有想法要检查什么。因此,如果有人能给我建议还需要测试什么或在 .net 中设置断点的位置以找到根本原因,那就太好了。或者甚至更好地找到解决方案/解决方法。
UPDATE:
更新:
I found out that I can reproduced the phenomenon also if the mouse pointer is just moved away from the application window (at least on our platforms). And the probability for the bug to occur seems to increase with the complexity of the user interface – my test app not always fails to recognize the click but a complex WPF app fails each time.
我发现如果鼠标指针刚离开应用程序窗口(至少在我们的平台上),我也可以重现这种现象。并且出现错误的可能性似乎随着用户界面的复杂性而增加——我的测试应用程序并非总是无法识别点击,而是一个复杂的 WPF 应用程序每次都会失败。
You should be able to reproduce it with the WPF developer studio (e.g. version 2013) on Windows 8.1 with a touch device:
您应该能够在 Windows 8.1 上使用 WPF 开发人员工作室(例如 2013 版)使用触摸设备重现它:
- have the developer studio open to cover only half of the touch screen
- move away the move so that the cursor points to the desktop area
- touch to a button (e.g. “start debugging” – the play button): In my case the first touch never causes a click event.
- 打开开发者工作室,只覆盖触摸屏的一半
- 移开移动,使光标指向桌面区域
- 触摸按钮(例如“开始调试”——播放按钮):在我的例子中,第一次触摸不会导致点击事件。
采纳答案by Michael Podlejska
It has turned out to be a BUG in WPF. There is a workaround available until a KB is released.
原来是WPF中的一个BUG。在发布 KB 之前,有一种解决方法可用。
The workaround is to call Mouse.Synchronize();in the PreviewTouchDownevent handler of the affected UIElement of MainWindow.
解决方法是调用MainWindow 受影响的 UIElementMouse.Synchronize();的PreviewTouchDown事件处理程序。
I tested it and it works fine.
我测试了它,它工作正常。
回答by apc
I had the same issue and found that disabling the RealTimeStylus (effectivly disabling touch support) worked for me and resulted in mouse events always being raised on touch.
我遇到了同样的问题,发现禁用 RealTimeStylus(有效禁用触摸支持)对我有用,并导致鼠标事件总是在触摸时引发。
We were using an industrial touchscreen with multitouch support on Windows 10.
我们在 Windows 10 上使用支持多点触控的工业触摸屏。
public static void DisableWPFTabletSupport()
{
// Get a collection of the tablet devices for this window.
TabletDeviceCollection devices = System.Windows.Input.Tablet.TabletDevices;
if (devices.Count > 0)
{
// Get the Type of InputManager.
Type inputManagerType = typeof(System.Windows.Input.InputManager);
// Call the StylusLogic method on the InputManager.Current instance.
object stylusLogic = inputManagerType.InvokeMember("StylusLogic",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, InputManager.Current, null);
if (stylusLogic != null)
{
// Get the type of the stylusLogic returned from the call to StylusLogic.
Type stylusLogicType = stylusLogic.GetType();
// Loop until there are no more devices to remove.
while (devices.Count > 0)
{
// Remove the first tablet device in the devices collection.
stylusLogicType.InvokeMember("OnTabletRemoved",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,
null, stylusLogic, new object[] { (uint)0 });
}
}
}
}

