[英]Draw, Click and drag a drawn graphics in Picturebox c#
I want to make a WinForm Application in c# that I can draw a graphic, like a rectangle, and after drawing, when I click on the rectangle, it will show 5 boxes, to let me drag it to resize, and when pointing on the middle of the rectangle, it able to move it to the new location in the picture box, how to do so?我想用c#做一个WinForm应用程序,我可以画一个图形,比如一个矩形,画完后,当我点击这个矩形时,它会显示5个框,让我拖动它来调整大小,当指向矩形的中间,它能够将它移动到图片框中的新位置,如何做到这一点?
Over the time I settled with following procedure for interactive pictures, such as schedules, CAD editors, or GUI designers:随着时间的推移,我对交互式图片采用了以下程序,例如日程表、CAD 编辑器或 GUI 设计器:
I use an System.Drawing.Image
for the content of the PictureBox
, which contains what has already been drawn .我使用
System.Drawing.Image
作为PictureBox
的内容,其中包含已绘制的内容。 So don't draw objects directly.所以不要直接绘制对象。 Create a
DataTable
(ie ID as Int32, ObjectType as String, Position as System.Drawing.Point, Dim1 as Double, Dim2 as Double
), where all drawn objects sit and where you'll be adding new.创建一个
DataTable
(即ID as Int32, ObjectType as String, Position as System.Drawing.Point, Dim1 as Double, Dim2 as Double
),所有绘制的对象都在其中,您将在其中添加新对象。 Then create a method, ie RefreshDrawing()
, that will draw all the objects in the table ( DrawElipse
for a "Circle" type, DrawLine
for "Line" type, etc.) into a Bitmap
and update PictureBox.Image
with this bitmap.然后创建一个方法,即
RefreshDrawing()
,它将把表中的所有对象(“圆形”类型的DrawElipse
,“线”类型的DrawLine
等)绘制DrawElipse
Bitmap
并用这个位图更新PictureBox.Image
。
if you want to find objects by mouse, you need to create an index table and record the objects position as described above.如果您想通过鼠标查找对象,您需要创建一个索引表并按照上述方法记录对象的位置。 You fill the table when creating an object (ie circle, rectangle, polygon, line,...).
您在创建对象(即圆形、矩形、多边形、线...)时填充表格。 I usually use center of object as a reference point (in your case it's the center of the central rectangle/handle).
我通常使用对象的中心作为参考点(在您的情况下,它是中央矩形/手柄的中心)。
On PictureBox1.MouseDown
...在
PictureBox1.MouseDown
...
starting mouse click coordinates are recorded开始鼠标点击坐标被记录
search the index table for object to be moved, using starting mouse coordinates - in your case, you can limit it to the area of your central handle, as you described in your post.使用起始鼠标坐标在索引表中搜索要移动的对象 - 在您的情况下,您可以将其限制在中央手柄的区域内,如您在帖子中所述。
set a status flag (you need to create one, ie a boolean variable), ie IsMoveMode = True
设置一个状态标志(你需要创建一个,即布尔变量),即
IsMoveMode = True
Now create/edit Paint
event.现在创建/编辑
Paint
事件。 Everything temporrary goes into temp event.所有临时的都进入临时事件。 So draw here objects representing the graphics that is being moved (or bounding box, or whatever you like) based on
PictureBox1.MouseMove
, while (and only while!) IsMoveMode = True
因此,基于
PictureBox1.MouseMove
在这里绘制代表正在移动的图形(或边界框,或任何您喜欢的东西)的对象,而(且仅当!) IsMoveMode = True
On PictureBox1.MouseUp
set IsMoveMode = False
and modify the object you moved in the objects index datatable, particularly the position of the object, and simply call method RefreshDrawing()
.在
PictureBox1.MouseUp
设置IsMoveMode = False
并修改您在对象索引数据表中移动的对象,特别是对象的位置,只需调用RefreshDrawing()
方法即可。 That will update the image and set it to the PictureBox.Image
.这将更新图像并将其设置为
PictureBox.Image
。 The temporrary graphics in the Paint
event will disapear automatically, since they apply only to "Move" mode. Paint
事件中的临时图形将自动消失,因为它们仅适用于“移动”模式。
Once you get objects to move, you can expand the logic analogically to resizing and other graphical operations too.一旦您让对象移动,您也可以将逻辑扩展为类似的调整大小和其他图形操作。
If it sounds complicated, believe me that for the result you're looking for it doesn't get more simple that this.如果这听起来很复杂,请相信我,对于您正在寻找的结果,没有比这更简单的了。 And it is very simple, when you get to understand the parts.
当您了解零件时,这非常简单。
Here is a complete (simplified) solution in VB.NET and C#:这是 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
Translated C#:翻译 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.