► 如前所述,您不应该使用CreateGraphics()
在 Control 的表面上绘制:该对象变得无效(属于past)一旦执行绘图的 Control 失效(重新绘制)。
所有具有可绘制表面的控件,都会引发Paint事件并有一个OnPaint我们可以重写来执行自定义绘画的方法(OnPaint
方法负责提高Paint
事件,所以我们只需要处理一个)。
事件和方法的参数代表一个绘制事件参数对象,它提供了一个fresh Graphics
我们可以用来绘画的对象。
我们可以调用无效()需要时重新绘制控件的方法。该方法会导致新的生成PaintEventArgs
对象(因此,一个新的 Graphics 对象)。之后OnPaint
方法被调用,这反过来又引发 Paint 事件。
► 要确定一个矩形是否与另一个(或多个)矩形相交,我们可以使用矩形.IntersetWith()方法(它返回true
or false
)和矩形.相交()方法 → 这用于生成一个表示其他两个矩形的交集的矩形。
也可以看看:
→ 矩形.包含([矩形])
→ 矩形.Union([矩形a],[矩形b]).
在这里,我使用一些集合来存储当前绘制的形状及其交集(只是矩形,但您可以使用以下命令构建更复杂的形状)图形路径对象):
- A
List<Rectangle>
(rects
)它存储已经创建的矩形。
- A
List<Rectangle>
(intersections
),存储交集属于过去(已经绘制了交叉点)。
- A
List<Rectangle>
(currentIntersects
),用于临时存储绘制新矩形形状时生成的交集,以便我们可以使用不同的颜色(一旦松开鼠标按钮,该集合即为fixed并添加到intersections
收藏)。
- 矩形结构(
currentRect
)它代表当前正在表面上绘制的矩形(当释放鼠标按钮时,该对象被添加到rects
收藏)。
- 点结构(
startPosition
),用于存储当前绘制的 Rectangle 的初始位置。当调用 OnMouseDown 方法时(当生成新的矩形形状时),它会重置。
► 要使用此代码,请创建一个新表单并将您在此处找到的代码粘贴到其代码文件中。不需要订阅任何事件:因为我们在表单上绘图,所以我重写了它的方法(OnPaint
, OnMouseDown
, OnMouseUp
, OnMouseMove
),不使用任何事件。
您可以对自定义控件或用户控件执行相同的操作。
要将这些集合或仅将交集集合添加到例如列表框以直观地处理集合,请参阅此处(currentIntersects
and intersections
集合已包含信息):
如何调用使用 PaintEventArgs 和坐标变量的方法
NOTE:
► 在这里,在OnPaint
方法重写,我没有调用base.OnPaint()
,因此不会生成事件。这会稍微加快该过程,但请记住,订阅表单的 Paint 事件是没有用的。
► 您需要激活双缓冲:(设置DoubleBuffered = true
),否则你会注意到很多闪烁(这是很正常的)。
它是这样工作的:
public partial class FormDrawings : Form
{
private List<Rectangle> rects = new List<Rectangle>();
private List<Rectangle> intersections = new List<Rectangle>();
private List<Rectangle> currentIntersects = new List<Rectangle>();
private Rectangle currentRect = Rectangle.Empty;
private Point startPosition = Point.Empty;
private float penSize = 2.0f;
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left) {
startPosition = e.Location;
currentRect = new Rectangle(startPosition, Size.Empty);
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left) {
if (e.Y < startPosition.Y) { currentRect.Location = new Point(currentRect.X, e.Y); }
if (e.X < startPosition.X) { currentRect.Location = new Point(e.X, currentRect.Y); }
currentRect.Size = new Size(Math.Abs(startPosition.X - e.X), Math.Abs(startPosition.Y - e.Y));
currentIntersects.Clear();
foreach (var rect in rects) {
if (currentRect.IntersectsWith(rect)) {
currentIntersects.Add(Rectangle.Intersect(currentRect, rect));
}
}
this.Invalidate();
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (currentRect.Size != Size.Empty) rects.Add(currentRect);
if (currentIntersects.Count > 0) {
intersections.AddRange(currentIntersects);
}
}
protected override void OnPaint(PaintEventArgs e)
{
using (var borderPen = new Pen(Color.LightGreen, penSize))
using (var iBrush = new SolidBrush(Color.FromArgb(128, Color.Orange)))
using (var crBrush = new SolidBrush(Color.FromArgb(128, Color.DeepSkyBlue))) {
intersections.ForEach(r => e.Graphics.FillRectangle(iBrush, r));
currentIntersects.ForEach(r => e.Graphics.FillRectangle(crBrush, r));
e.Graphics.DrawRectangle(borderPen, currentRect);
rects.ForEach(r => e.Graphics.DrawRectangle(borderPen, r));
}
}
}