【问题标题】:Jumpy and Incomplete XAML Window Drag with C# TouchMove使用 C# TouchMove 进行跳跃和不完整的 XAML 窗口拖动
【发布时间】:2016-08-11 18:55:11
【问题描述】:

我有一个用于触摸屏的未装饰的小 xaml 窗口。用户必须能够使用触摸和拖动来移动窗口。当前在触摸和拖动中,窗口向拖动的方向移动,但只是部分移动;并且似乎有两个窗口而不是一个,使触摸和拖动看起来很跳跃。

此行为表现在开发系统(使用 Visual Studio Professional 2015 的 Surface Pro 3)以及生产系统(Windows 7,无键盘或鼠标)上。

我基于 Microsoft 的 example 这个 C#。

using System.Windows;
using System.Windows.Input;

namespace XAMLApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private TouchDevice windowTouchDevice;
        private Point lastPoint;

        private void Circle_TouchUp(object sender, TouchEventArgs e)
        {
            // Do stuff.
        }

        private void Window_TouchDown(object sender, TouchEventArgs e)
        {
            e.TouchDevice.Capture(this);

            if (windowTouchDevice == null)
            {
                windowTouchDevice = e.TouchDevice;
                lastPoint = windowTouchDevice.GetTouchPoint(null).Position;
            }

            e.Handled = true;
        }

        private void Window_TouchMove(object sender, TouchEventArgs e)
        {
            if (e.TouchDevice == windowTouchDevice)
            {
                var currentTouchPoint = windowTouchDevice.GetTouchPoint(null);

                var deltaX = currentTouchPoint.Position.X - lastPoint.X;
                var deltaY = currentTouchPoint.Position.Y - lastPoint.Y;

                Top += deltaY;
                Left += deltaX;

                lastPoint = currentTouchPoint.Position;

                e.Handled = true;
            }
        }

        private void Window_TouchLeave(object sender, TouchEventArgs e)
        {
            if (e.TouchDevice == windowTouchDevice)
                windowTouchDevice = null;

            e.Handled = true;
        }
    }
}

这里有一些用于窗口的 xaml。

<Window x:Name="AppWindow" x:Class="XAMLApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:XAMLApp"
        mc:Ignorable="d"
        Title="XAML Application"
        Height="25" Width="25"
        AllowsTransparency="True" WindowStyle="None" ResizeMode="NoResize"
        ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollBarVisibility="Hidden"
        ShowInTaskbar="False" ToolTip="XAML Application" Topmost="True" UseLayoutRounding="True"
        MaxHeight="25" MaxWidth="25" MinHeight="25" MinWidth="25"
        Left="0" Top="0" Background="Transparent"
        TouchDown="Window_TouchDown"
        TouchMove="Window_TouchMove"
        TouchLeave="Window_TouchLeave">
    <Grid>
        <Ellipse x:Name="Circle" Fill="Black" HorizontalAlignment="Left"
                 Height="24" Margin="0" Stroke="Black" VerticalAlignment="Top"
                 Width="24" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Hidden"
                 TouchUp="Circle_TouchUp" />
    </Grid>
</Window>

我尝试将Grid 替换为Canvas。那没什么区别。我还尝试将 Manipulation 用作 Microsoft 的 demonstrated。尝试拖动窗口时,被告知转换对窗口无效。

如何使用鼠标左键单击并拖动使触摸和拖动的行为与DragMove() 相同?

【问题讨论】:

    标签: c# .net wpf windows xaml


    【解决方案1】:

    通过TouchDevice.GetTouchPoint方法检索到的TouchPoint与窗口的TopLeft属性不共享同一个坐标系。您需要做的就是将检索到的 X 和 Y 值转换为屏幕坐标:

    private void Window_TouchMove(object sender, TouchEventArgs e)
    {
        if (e.TouchDevice == windowTouchDevice)
        {
            var currentTouchPoint = windowTouchDevice.GetTouchPoint(null);
    
            var locationOnScreen = this.PointToScreen(new Point(currentTouchPoint.Position.X, currentTouchPoint.Position.Y));
    
            var deltaX = locationOnScreen.X - lastPoint.X;
            var deltaY = locationOnScreen.Y - lastPoint.Y;
    
            Top += deltaY;
            Left += deltaX;
    
            lastPoint = locationOnScreen;
    
            e.Handled = true;
        }
    }
    

    编辑:

    当然,不同坐标系的事情适用于整个项目,所以Window_TouchDown事件处理方法需要以类似的方式进行适配:

    private void Window_TouchDown(object sender, TouchEventArgs e)
    {
        e.TouchDevice.Capture(this);
    
        if (windowTouchDevice == null)
        {
            windowTouchDevice = e.TouchDevice;
            var currentTouchPoint = windowTouchDevice.GetTouchPoint(null);
            var locationOnScreen = this.PointToScreen(new Point(currentTouchPoint.Position.X, currentTouchPoint.Position.Y));
            lastPoint = locationOnScreen;
        }
    
        e.Handled = true;
    }
    

    【讨论】:

    • 啊,晚了几秒钟……但是如果您仍然感兴趣,我的回答可能会解释为什么您的原始解决方案不起作用。
    • 我会继续将赏金奖励给您,因为感谢您澄清问题。但是,您提供的代码实际上使 Window 从屏幕上消失,因此它可以使用编辑。我会将我的答案标记为答案,因为这是我解决问题的方式。非常感谢!
    • 你说得对,解决方案中缺少一点东西。我已经编辑了答案以给出全貌!
    • 漂亮!谢谢。
    【解决方案2】:

    代替

    Top += deltaY;
    Left += deltaX;
    

    我只是需要

    Top += currentTouchPoint.Position.Y;
    Left += currentTouchPoint.Position.X;
    

    呃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-01
      • 2017-03-22
      • 1970-01-01
      • 2014-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多