什么';旋转我的三星平板电脑后,导致WPF应用程序中的触摸输入被忽略?
我有一个WPF应用程序,我正在三星XE700T1A平板电脑上测试。我没有其他的药片来测试它。启动应用程序后,当我将平板电脑旋转到纵向模式时,我的UI元素停止对触摸做出响应。在再次旋转回风景区后,他们继续忽略触摸,但在第三次旋转回肖像区后,触摸起作用。进一步旋转似乎会产生不确定的结果。有时触摸可以工作,有时你必须不断旋转才能拿回它。我在最初的序列中看到了偶然的变化,但在大多数情况下,它看起来非常一致 为了缩小可能性的范围,我创建了一个简单的WPF应用程序来演示这个问题。代码如下: main window.xaml什么';旋转我的三星平板电脑后,导致WPF应用程序中的触摸输入被忽略?,wpf,touch,tablet,Wpf,Touch,Tablet,我有一个WPF应用程序,我正在三星XE700T1A平板电脑上测试。我没有其他的药片来测试它。启动应用程序后,当我将平板电脑旋转到纵向模式时,我的UI元素停止对触摸做出响应。在再次旋转回风景区后,他们继续忽略触摸,但在第三次旋转回肖像区后,触摸起作用。进一步旋转似乎会产生不确定的结果。有时触摸可以工作,有时你必须不断旋转才能拿回它。我在最初的序列中看到了偶然的变化,但在大多数情况下,它看起来非常一致 为了缩小可能性的范围,我创建了一个简单的WPF应用程序来演示这个问题。代码如下: main win
<Window x:Class="RotationBug.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock x:Name="DisplayText"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="I'm happy." />
<Button Grid.Row="1"
Height="22"
Width="80"
Margin="0,0,0,20"
Click="OnButtonPress"
Content="Depress Me" />
</Grid>
</Window>
这个简单的演示应用程序也被托管
有人知道是什么导致了这个问题吗?或者如何解决呢?有人能重现此问题吗?这显然是Microsoft内部已知的问题,其中“” 根据此处的注释,解决方法是订阅
SystemEvents.DisplaySettingsChanged
,并在短时间延迟后,将WM\u DISPLAYCHANGE
重新发布到当前线程中标题为“SystemResourceNotifyWindow”的窗口
然而,发布在那里的实际代码对于微软以外的任何人都不实用。下面的代码将适用于我们其他人。我已经发布了一个示例解决方案
class NativeRotationFix
{
私有只读窗口;
私有常量字符串MessageWindowTitle=“SystemResourceNotifyWindow”;
私有consuint WM_DISPLAYCHANGE=0x007E;
专用常数int延迟=500;
私有整数宽度;
私人内部高度;
私有整数深度;
公共代表bool WNDENUMPROC(IntPtr hWnd、IntPtr lParam);
[DllImport(“user32.dll”)]
公共静态外部布尔枚举线程窗口(uint dwThreadId、WNDENUMPROC lpfn、IntPtr lpram);
[DllImport(“user32.dll”)]
公共静态外部int GetWindowText(IntPtr hWnd、StringBuilder lpString、int nMaxCount);
[DllImport(“user32.dll”)]
公共静态外部bool PostMessage(IntPtr hWnd、uint msg、IntPtr wParam、IntPtr lParam);
[DllImport(“kernel32.dll”)]
静态外部uint GetCurrentThreadId();
公共NativeRotationFix(窗口)
{
this.window=窗口;
SystemEvents.DisplaySettingsChanged+=OnDisplaySettingsChanged;
}
~NativeRotationFix()
{
SystemEvents.DisplaySettingsChanged-=OnDisplaySettingsChanged;
}
私有void OnDisplaySettingsChanged(对象发送方,事件参数e)
{
新Dispatcher(TimeSpan.From毫秒(延迟),DispatcherPriority.Normal,(s,a)=>
{
WindowInteropHelper interopHelper=新的WindowInteropHelper(窗口);
Screen Screen=Screen.FromHandle(interopHelper.Handle);
宽度=screen.Bounds.width;
高度=screen.Bounds.height;
深度=screen.BitsPerPixel;
uint threadId=GetCurrentThreadId();
EnumThreadWindows(threadId、PostToNotifyWindow、IntPtr.Zero);
(作为调度员)。停止();
},Dispatcher.CurrentDispatcher);
}
私有bool PostToNotifyWindow(IntPtr hwnd、IntPtr lparam)
{
StringBuilder缓冲区=新的StringBuilder(MessageWindowTitle.Length+1);
如果(GetWindowText(hwnd,buffer,buffer.Capacity)你看到了吗?值得注意的是,gclassy的帖子。我不清楚gclassy是否解决了guy在该线程上的问题。谢谢,但这似乎并不相关。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnButtonPress(object sender, RoutedEventArgs e)
{
DisplayText.Text = DateTime.UtcNow.Ticks.ToString();
}
}
class NativeRotationFix
{
private readonly Window window;
private const string MessageWindowTitle = "SystemResourceNotifyWindow";
private const uint WM_DISPLAYCHANGE = 0x007E;
private const int Delay = 500;
private int width;
private int height;
private int depth;
public delegate bool WNDENUMPROC(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool EnumThreadWindows(uint dwThreadId, WNDENUMPROC lpfn, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
public NativeRotationFix(Window window)
{
this.window = window;
SystemEvents.DisplaySettingsChanged += OnDisplaySettingsChanged;
}
~NativeRotationFix()
{
SystemEvents.DisplaySettingsChanged -= OnDisplaySettingsChanged;
}
private void OnDisplaySettingsChanged(object sender, EventArgs e)
{
new DispatcherTimer(TimeSpan.FromMilliseconds(Delay), DispatcherPriority.Normal, (s, a) =>
{
WindowInteropHelper interopHelper = new WindowInteropHelper(window);
Screen screen = Screen.FromHandle(interopHelper.Handle);
width = screen.Bounds.Width;
height = screen.Bounds.Height;
depth = screen.BitsPerPixel;
uint threadId = GetCurrentThreadId();
EnumThreadWindows(threadId, PostToNotifyWindow, IntPtr.Zero);
(s as DispatcherTimer).Stop();
}, Dispatcher.CurrentDispatcher);
}
private bool PostToNotifyWindow(IntPtr hwnd, IntPtr lparam)
{
StringBuilder buffer = new StringBuilder(MessageWindowTitle.Length + 1);
if (GetWindowText(hwnd, buffer, buffer.Capacity) <= 0) return true;
if (buffer.ToString() != MessageWindowTitle) return true;
PostMessage(hwnd, WM_DISPLAYCHANGE, new IntPtr(depth), new IntPtr(MakeLong(width, height)));
return false;
}
private static int MakeLong(int low, int high)
{
return (int)((ushort)low | (uint)high << 16);
}
}