如何在运行时连接 shapes/labels 行?
How to connect with line shapes/labels on runtime?
我想在运行时创建 labels/shapes,然后像在 Visio 中那样用线连接形状。
使用此代码,我正在创建 "block":
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;
}
};
}
我该怎么做?至少如何搜索它?做这个的最好方式是什么?
这是一个最小的示例,您可以如何从稍微更改和扩展代码开始:
首先我们创建一个 class 级别变量来保存连接块的列表:
List<Tuple<Label, Label>> lines = new List<Tuple<Label, Label>>();
您可能想使用自己的 class 而不是便宜的 Tuples
来保存有关线条的更多信息,例如颜色、笔型、宽度等。
接下来我们把createBlock
方法return做成新的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>
一旦您将它们升级到 class Block
)以访问它们稍后,这样您就不必费力地浏览 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
}
};
}
我希望你的 canvas 是双缓冲的(或者 canvas 是 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);
}
}
有很多地方需要改进,但它确实有效而且相当简单。线条在标签后面,只要您不过度拥挤canvas,它们看起来就很自然..
关于 Winforms Graphics 有很多东西需要学习,但它们远远超出了本文的范围 post..
我想在运行时创建 labels/shapes,然后像在 Visio 中那样用线连接形状。
使用此代码,我正在创建 "block":
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;
}
};
}
我该怎么做?至少如何搜索它?做这个的最好方式是什么?
这是一个最小的示例,您可以如何从稍微更改和扩展代码开始:
首先我们创建一个 class 级别变量来保存连接块的列表:
List<Tuple<Label, Label>> lines = new List<Tuple<Label, Label>>();
您可能想使用自己的 class 而不是便宜的 Tuples
来保存有关线条的更多信息,例如颜色、笔型、宽度等。
接下来我们把createBlock
方法return做成新的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>
一旦您将它们升级到 class Block
)以访问它们稍后,这样您就不必费力地浏览 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
}
};
}
我希望你的 canvas 是双缓冲的(或者 canvas 是 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);
}
}
有很多地方需要改进,但它确实有效而且相当简单。线条在标签后面,只要您不过度拥挤canvas,它们看起来就很自然..
关于 Winforms Graphics 有很多东西需要学习,但它们远远超出了本文的范围 post..