Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';旋转我的三星平板电脑后,导致WPF应用程序中的触摸输入被忽略?_Wpf_Touch_Tablet - Fatal编程技术网

什么';旋转我的三星平板电脑后,导致WPF应用程序中的触摸输入被忽略?

什么';旋转我的三星平板电脑后,导致WPF应用程序中的触摸输入被忽略?,wpf,touch,tablet,Wpf,Touch,Tablet,我有一个WPF应用程序,我正在三星XE700T1A平板电脑上测试。我没有其他的药片来测试它。启动应用程序后,当我将平板电脑旋转到纵向模式时,我的UI元素停止对触摸做出响应。在再次旋转回风景区后,他们继续忽略触摸,但在第三次旋转回肖像区后,触摸起作用。进一步旋转似乎会产生不确定的结果。有时触摸可以工作,有时你必须不断旋转才能拿回它。我在最初的序列中看到了偶然的变化,但在大多数情况下,它看起来非常一致 为了缩小可能性的范围,我创建了一个简单的WPF应用程序来演示这个问题。代码如下: main win

我有一个WPF应用程序,我正在三星XE700T1A平板电脑上测试。我没有其他的药片来测试它。启动应用程序后,当我将平板电脑旋转到纵向模式时,我的UI元素停止对触摸做出响应。在再次旋转回风景区后,他们继续忽略触摸,但在第三次旋转回肖像区后,触摸起作用。进一步旋转似乎会产生不确定的结果。有时触摸可以工作,有时你必须不断旋转才能拿回它。我在最初的序列中看到了偶然的变化,但在大多数情况下,它看起来非常一致

为了缩小可能性的范围,我创建了一个简单的WPF应用程序来演示这个问题。代码如下:

main window.xaml

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