![](/img/trans.png)
[英]C# Draw on PictureBox with Graphics.DrawLine() not working on Paint event
[英]Draw, Click and drag a drawn graphics in Picturebox c#
随着时间的推移,我对交互式图片采用了以下程序,例如日程表、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.