如何在运行时与线形/标签连接? [英] How to connect with line shapes/labels on runtime?

查看:63
本文介绍了如何在运行时与线形/标签连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在运行时创建标签/形状,然后再将形状与线连接起来,就像在Visio中一样.

I want to create on runtime labels/shapes and after that to connect shapes with line like how you do it in Visio.

使用此代码,我将创建块":

With this code I am creating the "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);
                }
            }

以此,我以以下形式移动对象:

With this I am moving the objects in the form:

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;

                     }
                 }; 
            }

我实际上该如何做?至少如何搜索呢?做这个的最好方式是什么?

How do I actually do that? At least how to search for it? What is the best way to do this?

推荐答案

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

Here is a minimal example how you can start by changing and expanding your code a little:

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

first we create a class level variable to hold the list of connected blocks:

List<Tuple<Label, Label>> lines = new List<Tuple<Label, Label>>();

您可能想使用自己的类而不是便宜的 Tuples 来保存有关线条的更多信息,例如颜色,笔样式,宽度等.

You may want to use a class of your own instead of the cheap Tuples to hold more info about the lines, like color, pen style, width etc..

接下来,我们使 createBlock 方法返回新的 Label ,以便我们可以直接使用它.

Next we make the createBlock method return the new Label, so we can use it directly..

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 事件中使用它的方式:

Here is how I use it in my Form Load event:

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> 阻止)以供日后使用,因此您不必遍历 canvas.Controls 集合..

It is probably a good idea to put each block into a List<Label> or (List<Block> once you have upgraded them to a class Block) to access them later, so you don't have to wade through the canvas.Controls collection..

要显示行,我们需要在每次添加或移动行时触发 Paint 事件:

To make it show the lines, we need to trigger the Paint event each time a line is added or moved:

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 )!

I hope your canvas is double buffered (or that canvas is a 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);
    }
}

有很多需要改进的地方,但是很有效,而且很简单.线条在标签的后面,只要您不使画布过度拥挤,它们看起来就很自然.

There are many things to improve but it works and is rather simple. The lines are behind the Labels and as long you don't overcrowd the canvas they look rather natural..

关于Winforms Graphics有很多东西要学习,但是它们远远超出了本文的范围.

There are many things to learn about Winforms Graphics but they are well beyond the scope of this post..

这篇关于如何在运行时与线形/标签连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆