繁体   English   中英

在Picturebox c#中绘制,单击并拖动绘制的图形

[英]Draw, Click and drag a drawn graphics in Picturebox c#

我想用c#做一个WinForm应用程序,我可以画一个图形,比如一个矩形,画完后,当我点击这个矩形时,它会显示5个框,让我拖动它来调整大小,当指向矩形的中间,它能够将它移动到图片框中的新位置,如何做到这一点? 可拖动矩形图形

随着时间的推移,我对交互式图片采用了以下程序,例如日程表、CAD 编辑器或 GUI 设计器:

  • 我使用System.Drawing.Image作为PictureBox的内容,其中包含已绘制的内容 所以不要直接绘制对象。 创建一个DataTable (即ID as Int32, ObjectType as String, Position as System.Drawing.Point, Dim1 as Double, Dim2 as Double ),所有绘制的对象都在其中,您将在其中添加新对象。 然后创建一个方法,即RefreshDrawing() ,它将把表中的所有对象(“圆形”类型的DrawElipse ,“线”类型的DrawLine等)绘制DrawElipse Bitmap并用这个位图更新PictureBox.Image

  • 如果您想通过鼠标查找对象,您需要创建一个索引表并按照上述方法记录对象的位置。 您在创建对象(即圆形、矩形、多边形、线...)时填充表格。 我通常使用对象的中心作为参考点(在您的情况下,它是中央矩形/手柄的中心)。

  • PictureBox1.MouseDown ...

    • 开始鼠标点击坐标被记录

    • 使用起始鼠标坐标在索引表中搜索要移动的对象 - 在您的情况下,您可以将其限制在中央手柄的区域内,如您在帖子中所述。

    • 设置一个状态标志(你需要创建一个,即布尔变量),即IsMoveMode = True

  • 现在创建/编辑Paint事件。 所有临时的都进入临时事件。 因此,基于PictureBox1.MouseMove在这里绘制代表正在移动的图形(或边界框,或任何您喜欢的东西)的对象,(且仅当!) IsMoveMode = True

  • PictureBox1.MouseUp设置IsMoveMode = False并修改您在对象索引数据表中移动的对象,特别是对象的位置,只需调用RefreshDrawing()方法即可。 这将更新图像并将其设置为PictureBox.Image Paint事件中的临时图形将自动消失,因为它们仅适用于“移动”模式。

一旦您让对象移动,您也可以将逻辑扩展为类似的调整大小和其他图形操作。

如果这听起来很复杂,请相信我,对于您正在寻找的结果,没有比这更简单的了。 当您了解零件时,这非常简单。

这是 VB.NET 和 C# 中的完整(简化)解决方案:

Imports System.Drawing

Public Class DrawingForm
    Dim IndexTable As New DataTable
    Dim IsMoveMode As Boolean = False
    Dim MovedObjectID As Int32 = -1
    Dim MovePoint As Point = Nothing
    Private Sub DrawingForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        IndexTable.Columns.Add("ID", GetType(Int32))
        IndexTable.Columns.Add("ObjectType", GetType(String))
        IndexTable.Columns.Add("Position", GetType(Point))
        IndexTable.Columns.Add("Size", GetType(Size))

        ' Sample objects
        IndexTable.Rows.Add({1, "Rec", New Point(30, 50), New Size(100, 60)})
        IndexTable.Rows.Add({1, "Cir", New Point(200, 180), New Size(100, 100)})

        Call RefreshDrawing()
    End Sub

    Private Sub RefreshDrawing()
        Dim bmp As Bitmap
        'If Not IsNothing(PictureBox1.Image) Then
        '    bmp = PictureBox1.Image.Clone
        'Else
        '    bmp = New Bitmap(PictureBox1.Width, PictureBox1.Height)
        'End If
        bmp = New Bitmap(PictureBox1.Width, PictureBox1.Height)
        Using g As Graphics = Graphics.FromImage(bmp)
            For Each DrawingObject As DataRow In IndexTable.Rows
                Dim osize As Size = CType(DrawingObject("Size"), Size)
                Dim opos As Point = CType(DrawingObject("Position"), Point)
                Select Case DrawingObject("ObjectType")
                    Case "Rec"   ' Rectangle
                        g.FillRectangle(Brushes.DarkGreen, New Rectangle(opos.X - osize.Width / 2, opos.Y - osize.Height / 2, osize.Width, osize.Height))
                    Case "Cir"   ' Circle
                        g.FillEllipse(Brushes.PaleVioletRed, New Rectangle(opos.X - osize.Width / 2, opos.Y - osize.Height / 2, osize.Width, osize.Height))
                End Select
            Next
        End Using
        PictureBox1.Image = bmp
        PictureBox1.Invalidate()
    End Sub

    Private Function GetDrawingObject(MousePos As Point) As Int32
        Dim ClosestObjectRowID As Int32 = -1
        Dim ClosestPosition As Point = New Point(0, 0)
        For ir = 0 To IndexTable.Rows.Count - 1
            Dim oPos As Point = CType(IndexTable.Rows(ir)("Position"), Point)
            If Math.Sqrt((MousePos.X - oPos.X) ^ 2 + (MousePos.Y - oPos.Y) ^ 2) < Math.Sqrt((MousePos.X - ClosestPosition.X) ^ 2 + (MousePos.Y - ClosestPosition.Y) ^ 2) Then
                ClosestObjectRowID = ir
                ClosestPosition = oPos
            End If
        Next
        Return ClosestObjectRowID
    End Function

    Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
        MovedObjectID = GetDrawingObject(e.Location)
        IsMoveMode = True
    End Sub

    Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
        IsMoveMode = False
        Dim orow As DataRow = IndexTable.Rows(MovedObjectID)
        orow("Position") = e.Location
        MovedObjectID = -1
        Call RefreshDrawing()
    End Sub

    Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
        MovePoint = e.Location
        PictureBox1.Invalidate()
    End Sub

    Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
        If IsMoveMode = True AndAlso MovedObjectID >= 0 AndAlso Not IsNothing(MovePoint) Then
            Dim MovedObjectType As String = IndexTable.Rows(MovedObjectID)("ObjectType")
            Dim oPos As Point = MovePoint   ' CType(IndexTable.Rows(MovedObjectID)("Position"), Point)
            Dim oSize As Size = CType(IndexTable.Rows(MovedObjectID)("Size"), Size)
            ' Using g As Graphics = Graphics.FromImage(PictureBox1.Image)
            ' g.Clear(Color.White)
            Select Case MovedObjectType
                    Case "Rec"   ' Rectangle
                    e.Graphics.DrawRectangle(Pens.DarkGreen, New Rectangle(oPos.X - oSize.Width / 2, oPos.Y - oSize.Height / 2, oSize.Width, oSize.Height))
                Case "Cir"   ' Circle
                    e.Graphics.DrawEllipse(Pens.PaleVioletRed, New Rectangle(oPos.X - oSize.Width / 2, oPos.Y - oSize.Height / 2, oSize.Width, oSize.Height))
            End Select
            ' End Using
        End If
    End Sub
End Class

翻译 C#:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic;
using System.Drawing;

public class DrawingForm
{
    private DataTable IndexTable = new DataTable();
    private bool IsMoveMode = false;
    private Int32 MovedObjectID = -1;
    private Point MovePoint = null/* TODO Change to default(_) if this is not a reference type */;
    private void DrawingForm_Load(object sender, EventArgs e)
    {
        IndexTable.Columns.Add("ID", typeof(Int32));
        IndexTable.Columns.Add("ObjectType", typeof(string));
        IndexTable.Columns.Add("Position", typeof(Point));
        IndexTable.Columns.Add("Size", typeof(Size));

        // Sample objects
        IndexTable.Rows.Add(
        {
            1,
            "Rec",
            new Point(30, 50),
            new Size(100, 60)
        });
        IndexTable.Rows.Add(
        {
            1,
            "Cir",
            new Point(200, 180),
            new Size(100, 100)
        });

        RefreshDrawing();
    }

    private void RefreshDrawing()
    {
        Bitmap bmp;
        // If Not IsNothing(PictureBox1.Image) Then
        // bmp = PictureBox1.Image.Clone
        // Else
        // bmp = New Bitmap(PictureBox1.Width, PictureBox1.Height)
        // End If
        bmp = new Bitmap(PictureBox1.Width, PictureBox1.Height);
        using (Graphics g = Graphics.FromImage(bmp))
        {
            foreach (DataRow DrawingObject in IndexTable.Rows)
            {
                Size osize = (Size)DrawingObject("Size");
                Point opos = (Point)DrawingObject("Position");
                switch (DrawingObject("ObjectType"))
                {
                    case "Rec"   // Rectangle
                :
                        {
                            g.FillRectangle(Brushes.DarkGreen, new Rectangle(opos.X - osize.Width / (double)2, opos.Y - osize.Height / (double)2, osize.Width, osize.Height));
                            break;
                        }

                    case "Cir"   // Circle
            :
                        {
                            g.FillEllipse(Brushes.PaleVioletRed, new Rectangle(opos.X - osize.Width / (double)2, opos.Y - osize.Height / (double)2, osize.Width, osize.Height));
                            break;
                        }
                }
            }
        }
        PictureBox1.Image = bmp;
        PictureBox1.Invalidate();
    }

    private Int32 GetDrawingObject(Point MousePos)
    {
        Int32 ClosestObjectRowID = -1;
        Point ClosestPosition = new Point(0, 0);
        for (var ir = 0; ir <= IndexTable.Rows.Count - 1; ir++)
        {
            Point oPos = (Point)IndexTable.Rows(ir)("Position");
            if (Math.Sqrt(Math.Pow((MousePos.X - oPos.X), 2) + Math.Pow((MousePos.Y - oPos.Y), 2)) < Math.Sqrt(Math.Pow((MousePos.X - ClosestPosition.X), 2) + Math.Pow((MousePos.Y - ClosestPosition.Y), 2)))
            {
                ClosestObjectRowID = ir;
                ClosestPosition = oPos;
            }
        }
        return ClosestObjectRowID;
    }

    private void PictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        MovedObjectID = GetDrawingObject(e.Location);
        IsMoveMode = true;
    }

    private void PictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        IsMoveMode = false;
        DataRow orow = IndexTable.Rows(MovedObjectID);
        orow("Position") = e.Location;
        MovedObjectID = -1;
        RefreshDrawing();
    }

    private void PictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        MovePoint = e.Location;
        PictureBox1.Invalidate();
    }

    private void PictureBox1_Paint(object sender, PaintEventArgs e)
    {
        if (IsMoveMode == true && MovedObjectID >= 0 && !IsNothing(MovePoint))
        {
            string MovedObjectType = IndexTable.Rows(MovedObjectID)("ObjectType");
            Point oPos = MovePoint;   // CType(IndexTable.Rows(MovedObjectID)("Position"), Point)
            Size oSize = (Size)IndexTable.Rows(MovedObjectID)("Size");
            // Using g As Graphics = Graphics.FromImage(PictureBox1.Image)
            // g.Clear(Color.White)
            switch (MovedObjectType)
            {
                case "Rec"   // Rectangle
            :
                    {
                        e.Graphics.DrawRectangle(Pens.DarkGreen, new Rectangle(oPos.X - oSize.Width / (double)2, oPos.Y - oSize.Height / (double)2, oSize.Width, oSize.Height));
                        break;
                    }

                case "Cir"   // Circle
        :
                    {
                        e.Graphics.DrawEllipse(Pens.PaleVioletRed, new Rectangle(oPos.X - oSize.Width / (double)2, oPos.Y - oSize.Height / (double)2, oSize.Width, oSize.Height));
                        break;
                    }
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM