![](/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.