在 Wpf C# 中画一条直线

Posted

技术标签:

【中文标题】在 Wpf C# 中画一条直线【英文标题】:Draw a Straight Line In Wpf C# 【发布时间】:2021-01-02 00:03:09 【问题描述】:

您好,我正在我的 Application 中画一条线。我正在使用 Caliburn.Micro MVVM 框架。在我的 DICOM 图像中,我可以使用 Pointer 和 Calculate distance 绘制一条线。我使用 3 个事件 MouseDown、MouseMove 和 MouseUp。我左键单击鼠标,然后如果我释放 I able to Draw 则移动。我的问题是,当我移动鼠标时,有时可能会使用 Graphics.Drawline 画线改变方向,但是当我在最后一点时,它应该是 Straight line 。但是当我移动鼠标时,它的另一点也有不属于这条线的线。请看我做了什么

它应该是一条星线,因为有时我的鼠标移动颜色仍然在那个点。有一个著名的 DICOM Viewer App Name Radiant Here you can see 线是直的。 这是我的代码

  <Image    Grid.Row="3"  Grid.Column="2" Grid.ColumnSpan="4" 
                x:Name="DIIMGFINAL"  cal:Message.Attach="[Event MouseDown] = [Action MDownCalCulateDistance($source, $eventArgs)];
                 [Event MouseMove] = [Action MMoveCalCulateDistance($source, $eventArgs)];
                 [Event MouseUp] = [Action MUpCalCulateDistance($source, $eventArgs)]">
    </Image>

这是我在 ViewModel 类中的 C# 代码。这是 MouseDown 事件

  public void MDownCalCulateDistance(object sender, System.Windows.Input.MouseEventArgs e)
    

        if (!(sender is System.Windows.Controls.Image)) return;
        
        _diIMGTemp = DIIMGFINAL;
        if (_firstPoint.X == 0 && _firstPoint.Y == 0)
        
            System.Windows.Point px1 = e.GetPosition((System.Windows.Controls.Image)sender);

            _firstPoint = px1;
            
        
        if (_secondPoint.X != 0 && _secondPoint.Y != 0)
        
            System.Drawing.Bitmap drawbitmap = BitmapImage2Bitmap(DIIMGPrimary);
           
            Graphics g;
            using (g = Graphics.FromImage(drawbitmap))
            
                g.DrawLine(Pens.Red, Convert.ToInt32(_firstPoint.X), Convert.ToInt32(_firstPoint.Y), Convert.ToInt32(_secondPoint.X), Convert.ToInt32(_secondPoint.Y));
                g.Dispose();
            

            Convert_BitMap_BitImage(drawbitmap);
            DIIMGFINAL = DIIMGPrimary;

            var geometry = new FrameGeometry(DicomDataSet);
            var patientCoord1 = geometry.TransformImagePointToPatient(new Point2(Convert.ToInt32(_firstPoint.X), Convert.ToInt32(_firstPoint.Y)));
            var patientCoord2 = geometry.TransformImagePointToPatient(new Point2(Convert.ToInt32(_secondPoint.X), Convert.ToInt32(_secondPoint.Y)));
            double distanceInMM = patientCoord1.Distance(patientCoord2);
            DisTanceInMM = distanceInMM;
            //_firstPoint = new System.Windows.Point(0, 0);
            //_secondPoint= new System.Windows.Point(0, 0);
           // _isClicked = false;

        
    

这是 MouseUp 事件..

 public void MUpCalCulateDistance(object sender, System.Windows.Input.MouseEventArgs e)
    
        _firstPoint =  new System.Windows.Point(0, 0);
        _secondPoint = new System.Windows.Point(0, 0);
    

最后一个是鼠标移动事件。

 public void MMoveCalCulateDistance(object sender, System.Windows.Input.MouseEventArgs e)
    
        if (!(sender is System.Windows.Controls.Image)) return;

        System.Windows.Point px = e.GetPosition((System.Windows.Controls.Image)sender);

        XCoordinate = px.X;
        YCoordinate = px.Y;

        // if (_isClicked == false) return;
        // MousePoint
        if ((_firstPoint.X == 0 && _firstPoint.Y == 0))
        

            return;
        
        else
        
            System.Windows.Point px2 = e.GetPosition((System.Windows.Controls.Image)sender);
            _secondPoint = px2;
            System.Drawing.Bitmap drawbitmap = BitmapImage2Bitmap(DIIMGPrimary);
            Graphics g;
            // g.Clear();
            using (g = Graphics.FromImage(drawbitmap))
            
                g.DrawLine(Pens.Red, Convert.ToInt32(_firstPoint.X), Convert.ToInt32(_firstPoint.Y), Convert.ToInt32(_secondPoint.X), Convert.ToInt32(_secondPoint.Y));
            

            Convert_BitMap_BitImage(drawbitmap);
            DIIMGFINAL = DIIMGPrimary;

            var geometry = new FrameGeometry(DicomDataSet);
            var patientCoord1 = geometry.TransformImagePointToPatient(new Point2(Convert.ToInt32(_firstPoint.X), Convert.ToInt32(_firstPoint.Y)));
            var patientCoord2 = geometry.TransformImagePointToPatient(new Point2(Convert.ToInt32(_secondPoint.X), Convert.ToInt32(_secondPoint.Y)));
            double distanceInMM = patientCoord1.Distance(patientCoord2);
            DisTanceInMM = distanceInMM;
        

    

请帮助我提前致谢。对不起,冗长的问题。

【问题讨论】:

在每次鼠标移动时从 BitmapSource 转换为 Bitmap 并返回看起来非常低效。为什么不简单地在图像顶部的画布中绘制一条线?然后在鼠标向上修改位图。 感谢您的回答。您在 Canvas 和该图像中提出建议。我使用 bitmapImage 显示图像。因此,如果我想绘制,我将 bitmapimage 转换为 bitmap,而不是在 bitmap 中绘制然后 bitmapimage @Clemens 你能给我一些示例代码怎么做意味着 像这样 ***.com/a/63890185/1136211 谢谢@Clemens 我正在尝试这样做 【参考方案1】:

您可能不应该直接在图像上绘图。这是非常低效的,而且你也会遇到你遇到的问题。更好的方法是创建带有线条和其他图形的叠加层,请参阅问题how to bind lines to a canvas,了解如何执行此操作的示例。

如果您将项目控件和图像放在同一个网格中,则项目控件应该像叠加层一样工作。即

<Grid>
    <Image>
        <!--... -->
    </Image>
    <ItemsControl ItemsSource="Binding Lines">
        <!--...-->
    </ItemsControl>
</Grid>

您可以对位图叠加使用相同的方法,但这比让 wpf 为您绘制图元效率低。

【讨论】:

我可以从该图像中删除行吗 @rifat Murtuza 使用绑定的要点之一是添加/删除/移动行相当容易,所以是的。 谢谢 好的,我正在尝试这样做。 但是@JonasH 我应该如何使用 内部图像。我想是因为如果需要我必须删除 谢谢@JonasH 主要是它解决了。你能看看这个我已经与 MouseUp ***.com/questions/63911185/…

以上是关于在 Wpf C# 中画一条直线的主要内容,如果未能解决你的问题,请参考以下文章

用 g.DrawLine 画一条简单的垂直线

在jetpack compose中画一条线

如何在CAD中画平行线

如何利用OnDraw绘制直线

Unity实现任意两点之间画一条直线——bresenham算法(直线的处理)

如何在C#中画半透明的圆?