这是一个例子构成通过让图形所有嵌套控件都绘制其图形部分到他们自己身上。
诀窍是让他们都参与并改变Graphics
使复合无缝。
请注意,并非所有控件都支持Paint
适当地举办活动;最值得注意的是遗产TextBox
不会一起玩..
为了使其工作,我创建了一个类来存储图形数据;这很简单。对于更多涉及的东西,人们可以简单地扩展它......:
public class DrawAction
{
public Point p1 { get; set; }
public Point p2 { get; set; }
public Color c1 { get; set; }
public int mode { get; set; }
public DrawAction(Point p1_, Point p2_, Color c_, int mode_)
{
p1 = p1_; p2 = p2_; c1 = c_; mode = mode_;
}
public void Draw(Graphics g)
{
switch (mode)
{
case 0: // line
using (Pen pen = new Pen(c1))
g.DrawLine(pen, p1, p2);
break;
case 1: // rectangle
using (Pen pen = new Pen(c1))
g.DrawRectangle(pen, p1.X, p1.Y, p2.X - p1.X, p2.Y - p1.Y);
break;
case 2: // filled rectangle
using (SolidBrush brush = new SolidBrush(c1))
g.FillRectangle(brush, p1.X, p1.Y, p2.X - p1.X, p2.Y - p1.Y);
break;
default:
break;
}
}
}
我不会显示代码UserObject
。它包含一些控件,包括GroupBox
with a Radiobutton
在其中表明深度嵌套的控件仍然有效。
班级有一个Draw
可以调用的方法,传入一个有效的Graphics
object.
为了初始化,我们使用以下代码:
void initPainting(Control parent, Control baseCtl)
{
foreach (Control ctl in parent.Controls)
{
ctl.Paint += (s, e) =>
{
foreach (var drawing in drawings)
{
Point offset =
baseCtl.PointToClient(ctl.PointToScreen(Point.Empty));
Graphics g = e.Graphics;
g.TranslateTransform(-offset.X, -offset.Y);
drawing.Draw(g);
g.ResetTransform();
}
};
initPainting(ctl, baseCtl); // recursion
}
}
我使用 lambda 来连接Paint
所有控件的事件。
方法是递归的捕获公共父控件内的所有控件。
这是图形列表..
List<DrawAction> drawings = new List<DrawAction>();
及其初始化:
..
InitializeComponent();
Size sz = tableLayoutPanel1.Size;
drawings.Add(
new DrawAction(Point.Empty, new Point(sz.Width, sz.Height), Color.Red, 0));
drawings.Add(
new DrawAction(new Point(0, sz.Height), new Point(sz.Width, 0), Color.Blue, 0));
drawings.Add(
new DrawAction(new Point(50, 50), new Point(300, 300), Color.Green, 1));
initPainting(tableLayoutPanel1, tableLayoutPanel1);
这是结果和设计者的视图:
您可以看到TextBoxes
不要一起玩;还有一个小故障GroupBoxes
,不知道为什么..