我想在运行时标签/形状上创建,之后用线条连接形状,就像在Visio中一样。
使用此代码,我创建了"块":
private void createBlock() {
try {
Label label = new Label();
label.AutoSize = false;
label.Location = Control.MousePosition;
label.Size = new Size(89, 36);
label.BackColor = Color.DarkOliveGreen;
label.ForeColor = Color.White;
label.FlatStyle = FlatStyle.Flat;
label.TextAlign = ContentAlignment.MiddleCenter;
label.Text = "New Block";
label.ContextMenuStrip = contextBlock;
canvas.Controls.Add(label);
MoveBlock(label);
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
有了这个,我正在移动表格中的对象:
private void MoveBlock(Label block, Label endBlock=null){
block.MouseDown += (ss, ee) => {
if (ee.Button == System.Windows.Forms.MouseButtons.Left) fPoint = Control.MousePosition;
};
block.MouseMove += (ss, ee) => {
if (ee.Button == System.Windows.Forms.MouseButtons.Left) {
Point temp = Control.MousePosition;
Point res = new Point(fPoint.X - temp.X, fPoint.Y - temp.Y);
block.Location = new Point(block.Location.X - res.X, block.Location.Y - res.Y);
fPoint = temp;
}
};
}
我该怎么做?至少如何搜索它?做这个的最好方式是什么?
答案 0 :(得分:2)
以下是一个最小的示例,您可以通过稍微更改和扩展代码来开始:
首先我们创建一个类级变量来保存连接块的列表:
List<Tuple<Label, Label>> lines = new List<Tuple<Label, Label>>();
您可能希望使用自己的类而不是便宜的Tuples
来保存有关线条的更多信息,例如颜色,笔样式,宽度等。
接下来,我们让createBlock
方法返回新的Label
,以便我们可以直接使用它。
private Label createBlock() <---- for convenience!
{
try
{
Label label = new Label();
label.AutoSize = false;
label.Location = Control.MousePosition;
label.Size = new Size(89, 36);
label.BackColor = Color.DarkOliveGreen;
label.ForeColor = Color.White;
label.FlatStyle = FlatStyle.Flat;
label.TextAlign = ContentAlignment.MiddleCenter;
label.Text = "New Block";
label.ContextMenuStrip = contextBlock;
canvas.Controls.Add(label);
MoveBlock(label);
return label; <---- for convenience!
} catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return null;
}
以下是我在Form Load
事件中使用它的方法:
private void Form1_Load(object sender, EventArgs e)
{
Label l1 = createBlock();
Label l2 = createBlock();
lines.Add(new Tuple<Label, Label>(l1,l2));
}
将每个块放入List<Label>
或(List<Block>
一旦将它们升级为类Block
)以便稍后访问它们可能是个好主意,所以你不要# 39; t必须涉及canvas.Controls
集合......
要使其显示线条,我们需要在每次添加或移动线条时触发Paint
事件:
private void MoveBlock(Label block, Label endBlock = null)
{
block.MouseDown += (ss, ee) =>
{
if (ee.Button == System.Windows.Forms.MouseButtons.Left)
fPoint = Control.MousePosition;
};
block.MouseMove += (ss, ee) =>
{
if (ee.Button == System.Windows.Forms.MouseButtons.Left)
{
Point temp = Control.MousePosition;
Point res = new Point(fPoint.X - temp.X, fPoint.Y - temp.Y);
block.Location = new Point(block.Location.X - res.X,
block.Location.Y - res.Y);
fPoint = temp;
canvas.Invalidate(); // <------- draw the new lines
}
};
}
我希望你的画布是双缓冲的(或画布是PictureBox
)!
以下是绘制线条的简单实现:
private void canvas_Paint(object sender, PaintEventArgs e)
{
foreach (Tuple<Label, Label> t in lines)
{
Point p1 = new Point(t.Item1.Left + t.Item1.Width / 2,
t.Item1.Top + t.Item1.Height / 2);
Point p2 = new Point(t.Item2.Left + t.Item2.Width / 2,
t.Item2.Top + t.Item2.Height / 2);
e.Graphics.DrawLine(Pens.Black, p1, p2);
}
}
有许多事情需要改进,但它有效并且相当简单。线条在标签后面,只要你不过度拥抱画布,它们看起来就很自然..
关于Winforms Graphics有很多东西需要学习,但它们远远超出了本篇文章的范围..