簡體   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