Wpf 在MouseMove lag上绘制画布形状

Wpf 在MouseMove lag上绘制画布形状,wpf,Wpf,我有一个非常简单的场景:有一个画布,我需要使用MouseMove在画布上画一条线。但当我移动鼠标指针时,第二行的点(在“鼠标移动”中设置)与当前鼠标位置不匹配 UPD 2: Delta取决于鼠标的速度,若速度较大,则Delta较大且明显(滞后)。我注意到,如果你移动鼠标的速度不是很快也不是很慢,这个错误会更明显 您可以下载示例项目 当鼠标快速移动时,如图所示: 一些源代码: <Window x:Class="WpfApplication32.MainWindow" xmlns="

我有一个非常简单的场景:有一个画布,我需要使用MouseMove在画布上画一条线。但当我移动鼠标指针时,第二行的点(在“鼠标移动”中设置)与当前鼠标位置不匹配

UPD 2: Delta取决于鼠标的速度,若速度较大,则Delta较大且明显(滞后)。我注意到,如果你移动鼠标的速度不是很快也不是很慢,这个错误会更明显

您可以下载示例项目

当鼠标快速移动时,如图所示:

一些源代码:

<Window x:Class="WpfApplication32.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow"
    Width="525"
    Height="350">
<Canvas x:Name="MainCanvas"
        MouseLeftButtonDown="MainCanvas_OnMouseLeftButtonDown"
        MouseMove="MainCanvas_OnMouseMove"
        Background="White"
        />

使用System.Windows;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Shapes;
命名空间WpfApplication32
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
专用线路_currentLine;
私有布尔图;
公共主窗口()
{
初始化组件();
此.Loaded+=已加载;
}
已加载专用void(对象发送方,RoutedEventArgs RoutedEventArgs)
{
maincavas.Focus();
}
private void MainCanvas_OnMouseLeftButtonDown(对象发送器,MouseButtonEventArgs e)
{
如果(_isDrawing)
{
_currentLine=null;
_isDrawing=false;
返回;
}
_isDrawing=true;
_currentLine=newline(){Stroke=Brushes.Green};
var p=e.GetPosition(主画布);
_currentLine.X1=p.X;
_currentLine.Y1=p.Y;
_currentLine.X2=p.X;
_currentLine.Y2=p.Y;
maincavas.Children.Add(_currentLine);
}
private void MainCanvas_OnMouseMove(对象发送方,MouseEventArgs e)
{
如果(_currentLine==null)
返回;
var p=e.GetPosition(主画布);
_currentLine.X2=p.X;
_currentLine.Y2=p.Y;
}
}
}
我曾尝试使用CompositeTarget.Render和计时器每20毫秒更改一次第二个点,但没有效果

我有一个遗留项目,其中的代码很大程度上依赖于这种方法(canvas mouseMove和shapes)。所以我需要最简单的方法来消除这个滞后或者一些关于这个错误原因的想法)谢谢

UPD: 我试着用这个问题录制视频,但我不擅长。以下是我录制的一些屏幕,显示问题:

UPD 2: 我已经尝试过在没有画布的情况下使用窗口对象的OnRender来做同样的事情。我已经用DataContext画出了一条线——这里也有同样的问题。DataContext被认为比画布和线条(形状)更快。所以这不是画布问题

我还尝试使用WritableBitmap来画线-没有区别


我认为MouseMove事件可能有问题-我读到如果有很多对象(不是我的情况,但仍然是),MouseMove可能会延迟触发,所以我使用Win32 WM_MouseMove,但也没有帮助。在我的例子中,MW_MOUSEMOVE和wpf MOUSEMOVE事件之间的延迟是无法修复的,因为这是由于wpf的内部渲染系统造成的。即使可视化树很简单,也总是会有延迟。复杂的视觉树会导致更多的延迟。我花了很多时间试图解决这个问题。

尝试使用
MouseMove
事件,而不是在主画布上,而是在窗口本身上。 我最近在
Image
上使用
MouseMove
时遇到了同样的问题,结果非常糟糕 切换到window的活动对我帮助很大

<Window x:Name="Window1" x:Class="WpfApp2.MViewer"
        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:WpfApp2"
        mc:Ignorable="d"
        Title="MViewer" Height="454.411" Width="730.515" Loaded="Window_Loaded" Closing="Window1_Closing" ContentRendered="Window1_ContentRendered" MouseMove="Window1_MouseMove">
    <Grid>
        <Image x:Name="Image1" MouseMove="Image1_MouseMove"/>
        <Line Name="Line1" Visibility="Visible" Stroke="Red" StrokeThickness="0.75" />
        <Line Name="Line2" Visibility="Visible" Stroke="Red" StrokeThickness="0.75" />
    </Grid>
</Window>

您好,我已经尝试了您的源代码,它工作得很好,我没有看到线条边缘和当前鼠标位置之间的任何偏移!!。。。你用的是什么网络?嗨@joseph,我用的是.NET4.0。我的CPU是i3570k,我使用hd4000集成视频卡。但这个问题不仅仅发生在我的机器上,我在我的队友机器和客户机器上重现了它。可能我的描述不正确)当您快速移动鼠标时,偏移会出现,线的第二点开始与当前鼠标位置不匹配。速度更快-第二个点和当前鼠标位置之间的空间更大(滞后)。ThanksI出于同样的目的使用了
inkCanvas
,没有遇到任何问题。也许你可以试一下。InkCanvas也有同样的问题。据我所知,这是无法修复的,因为由于WPF internal render system.Oh,将始终存在延迟。我也遇到了这个问题。我想WPF根本不擅长快速绘图。。
<Window x:Name="Window1" x:Class="WpfApp2.MViewer"
        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:WpfApp2"
        mc:Ignorable="d"
        Title="MViewer" Height="454.411" Width="730.515" Loaded="Window_Loaded" Closing="Window1_Closing" ContentRendered="Window1_ContentRendered" MouseMove="Window1_MouseMove">
    <Grid>
        <Image x:Name="Image1" MouseMove="Image1_MouseMove"/>
        <Line Name="Line1" Visibility="Visible" Stroke="Red" StrokeThickness="0.75" />
        <Line Name="Line2" Visibility="Visible" Stroke="Red" StrokeThickness="0.75" />
    </Grid>
</Window>
        private void Window1_MouseMove(object sender, MouseEventArgs e)
        {
            Line1.Visibility = Visibility.Visible;
            Line1.X1 = Mouse.GetPosition(this).X;
            Line1.X2 = Mouse.GetPosition(this).X;
            Line1.Y1 = 0;
            Line1.Y2 = Window1.Height;

            Line2.Visibility = Visibility.Visible;
            Line2.X1 = 0;
            Line2.X2 = Window1.Width;
            Line2.Y1 = Mouse.GetPosition(this).Y;
            Line2.Y2 = Mouse.GetPosition(this).Y;
        }