.net 触摸WPF按钮有时不会调用Windows 8下的单击处理程序

.net 触摸WPF按钮有时不会调用Windows 8下的单击处理程序,.net,wpf,touch,windows-8.1,.net,Wpf,Touch,Windows 8.1,“当应用程序窗口没有焦点时,有时按钮触摸时不会调用单击处理程序。” 系统: 带有多点触摸输入设备的Windows 8.1 软件: 一个简单的WPF 4.5.2应用程序,只有一个按钮,在调用单击处理程序时记录(只需创建一个新项目,并将一个带有单击处理程序的按钮添加到主窗口) 现象: 通常,当触摸按钮时,会调用其单击处理程序但当应用程序窗口没有焦点时,有时按钮触摸时不会调用单击处理程序(尽管按钮颜色变为蓝色)。当应用程序窗口已经有焦点时,触摸按钮一直有效。 这种情况有时会发生,但在使用不同触摸硬件(

“当应用程序窗口没有焦点时,有时按钮触摸时不会调用单击处理程序。”

系统:

带有多点触摸输入设备的Windows 8.1

软件:

一个简单的WPF 4.5.2应用程序,只有一个按钮,在调用单击处理程序时记录(只需创建一个新项目,并将一个带有单击处理程序的按钮添加到主窗口)

现象:

通常,当触摸按钮时,会调用其单击处理程序但当应用程序窗口没有焦点时,有时按钮触摸时不会调用单击处理程序(尽管按钮颜色变为蓝色)。当应用程序窗口已经有焦点时,触摸按钮一直有效。 这种情况有时会发生,但在使用不同触摸硬件(所有windows 8.1)的各种系统上都会发生。我从未在Windows7上体验过。 无论窗口是否聚焦,鼠标都可以工作

(在发布和调试模式下发生,无论是否连接调试器)

测试:

我检查了windows中的各种触摸设置并玩了起来。我还重新校准了触摸->无差异

检查WPF按钮鼠标和触摸事件时,在错误情况下,最后收到的事件是PreviewMouseUp,但没有单击

当我查看收到的窗口消息(spy++)时,我得到以下信息(为了更好地查看,删除了WM_IME_SETCONTEXT、WM_GETTEXT、WM_NCHITTEST、WM_GETOBJECT):

收到点击:

单击未收到

在这个错误中有额外的行

S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_LBUTTONUP
R WM_SETCURSOR fHaltProcessing:False
在WM_LBUTTONUP之前。但我不知道这是否重要

我已经尝试调试.net代码,以查看哪种条件导致不调用Click处理程序,但很快就在System.Windows.Input.InputManager和System.Windows.Input.StylusLogic的PromoteMainToMouse()函数中迷失了方向

我真的不知道该检查什么了。 因此,如果有人能给我一些建议,告诉我还需要测试什么,或者在.net中设置断点以找到根本原因,那就太好了。或者更好地找到解决方案/解决方法

更新:

我发现,如果鼠标指针刚刚离开应用程序窗口(至少在我们的平台上),我也可以重现这种现象。随着用户界面的复杂性,bug发生的概率似乎也在增加——我的测试应用程序并不总是无法识别点击,但一个复杂的WPF应用程序每次都会失败

您应该能够使用触摸设备在Windows 8.1上的WPF developer studio(例如2013版)进行复制:

  • 打开开发者工作室,只覆盖触摸屏的一半
  • 移开移动,使光标指向桌面区域
  • 触摸按钮(例如“开始调试”-播放按钮):在我的情况下,第一次触摸不会导致点击事件

事实证明,这是WPF中的一个BUG。在发布知识库之前,有一个变通方法可用

解决方法是调用
Mouse.Synchronize()PreviewTouchDown
事件处理程序中的code>


我对它进行了测试,效果很好。

我也遇到了同样的问题,发现禁用RealTimeStylus(有效地禁用触摸支持)对我有效,并导致触摸时总是引发鼠标事件

我们在Windows10上使用了支持多点触摸的工业触摸屏


Microsoft修补程序现在可用:您的MS链接已断开。不,我测试了它(2016年7月22日),它工作正常。这很奇怪,我仍然收到
“对不起,您请求的页面不可用。”
刚从另一台计算机上试用过。当我到达一个页面,必须首先接受“Microsoft服务协议”时,它就会起作用。url将更改为
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
S WM_SETCURSOR hwnd:000503F8 nHittest:HTCLIENT wMouseMsg:WM_LBUTTONUP
R WM_SETCURSOR fHaltProcessing:False
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 });  
            }                  
        }  

    }  
}