在控件的表面上绘图时,您始终使用该控件的Paint 事件或覆盖自定义/用户控件的OnPaint 方法。
不要尝试存储其Graphics 对象:一旦控件失效(重新绘制),它就会变得无效。
使用PaintEventArgs对象提供的Graphics对象。
当需要更复杂的过程来绘制不同的形状时,您可以将e.Graphics 对象传递给不同的方法,这些方法将使用该对象来执行专门的绘图。
在示例中,每个绘制的形状的坐标和其他属性都分配给一个专门的类DrawingRectangle(这里是一个简化的结构,它可以包含更复杂的功能)。
List<DrawingRectangle>() 存储在 session 中生成的所有 DrawingRectangle 对象的引用(直到绘图被清除)。
每次在 Control 的表面上生成 Left MouseDown 事件时,都会将一个新的 DrawingRectangle 对象添加到列表中。
e.Location 存储为DrawingRectangle.StartPoint(一个不会改变的值)和DrawingRectangle.Location:当鼠标指针移动时,这个值将被更新。
当鼠标移动时,当前的e.Location 值会从之前存储的起点坐标中减去。一个简单的计算就可以从各个方向绘制形状。
此度量确定矩形的当前大小。
要从绘图中删除一个矩形,您只需从列表中删除它的引用和Invalidate()提供绘图表面的控件。
要清除绘图表面,请清除List<DrawingRectangle>() (drawingRects.Clear()) 并调用Invalidate()。
这里还有一些其他示例:
Transparent Overlapping Circular Progress Bars
GraphicsPath and Matrix classes
Connecting different shapes
Drawing Transparent/Translucent Custom Controls
// Assign the Color used to draw the border of a shape to this Field
Color SelectedColor = Color.LightGreen;
List<DrawingRectangle> drawingRects = new List<DrawingRectangle>();
public class DrawingRectangle
{
public Rectangle Rect => new Rectangle(Location, Size);
public Size Size { get; set; }
public Point Location { get; set; }
public Control Owner { get; set; }
public Point StartPosition { get; set; }
public Color DrawingcColor { get; set; } = Color.LightGreen;
public float PenSize { get; set; } = 3f;
}
private void form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
DrawingRects.Add(new DrawingRectangle() {
Location = e.Location,
Size = Size.Empty,
StartPosition = e.Location,
Owner = (Control)sender,
DrawingcColor = SelectedColor // <= Shape's Border Color
});
}
private void form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
var dr = DrawingRects[DrawingRects.Count - 1];
if (e.Y < dr.StartPosition.Y) { dr.Location = new Point(dr.Rect.Location.X, e.Y); }
if (e.X < dr.StartPosition.X) { dr.Location = new Point(e.X, dr.Rect.Location.Y); }
dr.Size = new Size(Math.Abs(dr.StartPosition.X - e.X), Math.Abs(dr.StartPosition.Y - e.Y));
this.Invalidate();
}
private void form1_MouseUp(object sender, MouseEventArgs e)
{
// The last drawn shape
var dr = DrawingRects.Last();
// ListBox used to present the shape coordinates
lstPoints.Items.Add($"{dr.Location}, {dr.Size}");
}
private void form1_Paint(object sender, PaintEventArgs e)
{
DrawShapes(e.Graphics);
}
private void DrawShapes(Graphics g)
{
if (DrawingRects.Count == 0) return;
g.SmoothingMode = SmoothingMode.AntiAlias;
foreach (var dr in DrawingRects) {
using (Pen pen = new Pen(dr.DrawingcColor, dr.PenSize)) {
g.DrawRectangle(pen, dr.Rect);
};
}
}
// A Button used to save the current drawing to a Bitmap
private void btnSave_Click(object sender, EventArgs e)
{
using (var bitmap = new Bitmap(panCanvas.ClientRectangle.Width, panCanvas.ClientRectangle.Height))
using (var g = Graphics.FromImage(bitmap)) {
DrawShapes(g);
bitmap.Save(@"[Image Path]", ImageFormat.Png);
// Clone the Bitmap to show a thumbnail
}
}
// A Button used to clear the current drawing
private void btnClear_Click(object sender, EventArgs e)
{
drawingRects.Clear();
this.Invalidate();
}