如何在运行时连接线形/标签?

时间:2015-07-25 11:33:01

标签: c# runtime graphics2d

我想在运行时标签/形状上创建,之后用线条连接形状,就像在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;

                     }
                 }; 
            }

我该怎么做?至少如何搜索它?做这个的最好方式是什么?

1 个答案:

答案 0 :(得分:2)

以下是一个最小的示例,您可以通过稍微更改和扩展代码来开始:

enter image description here

首先我们创建一个类级变量来保存连接块的列表:

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有很多东西需要学习,但它们远远超出了本篇文章的范围..