C#使用TextBox绘制线条

时间:2015-04-12 04:09:56

标签: c# drawing lines

我有一个应用程序,我可以在屏幕上添加一个textBox并移动它。 当我添加两个以上的文本框时,我双击两个文本框的顶部,一条线连接两个文本框。

我的问题是:如何使该行与textBox一起移动? 代码如下:

public partial class principal : Form
{
    int posMouseFormX, posMouseFormY;
    int posMouseTXT_X, posMouseTXT_Y;
    int posActTXT_X, posActTXT_Y;
    bool txtPressionado = false;
    int qntClick;
    Pen myPen = new Pen(System.Drawing.Color.DarkGreen, 1);
    Graphics Tela;
    List<TextBox> listaNós = new List<TextBox>();
    List<Point> origem = new List<Point>();
    List<Point> destino = new List<Point>();
    Point ponto1, ponto2;
    ContextMenuStrip menu;

    public principal()
    {
        InitializeComponent();
        menu = new ContextMenuStrip();
        menu.Items.Add("Remover");
        menu.ItemClicked += new ToolStripItemClickedEventHandler(contextMenuStrip1_ItemClicked);
    }

    //TextBox event when the mouse moves over the TXT
    private void txtMover_MouseMove(object sender, MouseEventArgs e)
    {
        TextBox textBox = sender as TextBox;

        posMouseFormX = textBox.Location.X + e.Location.X;
        posMouseFormY = textBox.Location.Y + e.Location.Y;

        if (txtPressionado == true) moverTxt(textBox);
    }

    //Retrieve the X and Y coordinates where clicked within the component. 
    private void txtMover_MouseDown(object sender, MouseEventArgs e)
    {
        posMouseTXT_X = e.Location.X;
        posMouseTXT_Y = e.Location.Y;
        txtPressionado = true;
    }

    private void txtMover_MouseUp(object sender, MouseEventArgs e)
    {
        txtPressionado = false;
    }

    private void moverTxt(TextBox a)
    {
        a.Location = new System.Drawing.Point(posMouseFormX - posMouseTXT_X, posMouseFormY - posMouseTXT_Y);
        posActTXT_X = a.Location.X;
        posActTXT_Y = a.Location.Y;

        System.Drawing.Graphics graphicsObj;
        graphicsObj = this.CreateGraphics();
    }

    //insert new TextBox
    private void sb_Inserir_No_Click(object sender, EventArgs e)
    {

        TextBox noFilho = new TextBox();

        noFilho = new System.Windows.Forms.TextBox();
        noFilho.Location = new System.Drawing.Point(379, 284);
        noFilho.Size = new System.Drawing.Size(100, 30);
        noFilho.TabIndex = 20;
        noFilho.Text = "";
        noFilho.BackColor = Color.White;

        posActTXT_X = noFilho.Location.X;
        posActTXT_Y = noFilho.Location.Y;

        this.Controls.Add(noFilho);
        noFilho.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
        noFilho.DoubleClick += new System.EventHandler(this.textBox1_Click);
        noFilho.MouseUp += new System.Windows.Forms.MouseEventHandler(txtMover_MouseUp);
        noFilho.MouseDown += new System.Windows.Forms.MouseEventHandler(txtMover_MouseDown);
        noFilho.MouseMove += new System.Windows.Forms.MouseEventHandler(txtMover_MouseMove);
        noFilho.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);

        noFilho.ContextMenuStrip = menu;   
    }

    //event to resize the txt on the screen as the content.
    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        TextBox textBox1 = sender as TextBox;
        Size size = TextRenderer.MeasureText(textBox1.Text, textBox1.Font);
        textBox1.Width = size.Width + 10;
        textBox1.Height = size.Height;
    }

    //Event to control the connection between two give us when double click on the textbox
    private void textBox1_Click(object sender, EventArgs e)
    {
        TextBox textBox1 = sender as TextBox;
        int meio = textBox1.Size.Width / 2;
        Tela = CreateGraphics();

        qntClick = qntClick + 1;

        if (this.qntClick == 1)
        {
            origem.Add(ponto1);
            ponto1 = new Point(textBox1.Location.X + meio, textBox1.Location.Y);
        }
        if (this.qntClick == 2)
        {
            qntClick = 0;
            destino.Add(ponto2);
            ponto2 = new Point(textBox1.Location.X + meio, textBox1.Location.Y);
            DesenhaSeta(Tela, ponto1, ponto2);
        }
    }

    //draw arrow between two TXT
    void DesenhaSeta(Graphics Tela, Point x, Point y)
    {
        myPen.StartCap = LineCap.Triangle;
        myPen.EndCap = LineCap.ArrowAnchor;
        Tela.DrawLine(myPen, x, y);
    }

    private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
        ContextMenuStrip menu = sender as ContextMenuStrip;
        //recuperando o controle associado com o contextmenu
        Control sourceControl = menu.SourceControl;

        DialogResult result = MessageBox.Show("Tem Certeza que deseja remover o nó selecionado?", "Excluir", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

        if(result == DialogResult.Yes)
        {
            sourceControl.Dispose();
        }
    }

    private void textBox1_KeyDown(object sender, KeyEventArgs e)
    {
        // Determine whether the key entered is the F1 key. Display help if it is.
        if (e.KeyCode == Keys.Space)
        {
            TextBox textBox1 = sender as TextBox;
            novoNó tela = new novoNó(textBox1.Text);
            tela.Show();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

包含的每个控件TextBox都有Move个事件。在那里拨打Invalidate()电话!

这些行应该在容纳Paint的容器的TextBoxes事件中绘制,可能是Form;如果是Form确实称为this.Invalidate()

请将线条图代码从DoubleClick事件移到Paint事件中,否则线条将不会持续存在,例如最小化/最大化事件或其他情况,系统必须重绘时应用!

您可能需要创建一个数据结构来维护有关哪些TextBox - 对需要连接的信息,可能是List<Tuple>List<someStructure>。这将在DoubleClick事件中填充/修改,然后调用this.Invalidate()并在Form.PaintforeachTextBox对列表进行调用..

如果您正在使用Form,请确保开启DoubleBuffered

更新:要比较这些结果,这是TextBoxes预计两个Form的最小示例:

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
        this.DoubleBuffered = true;
        pairs.Add(new Tuple<Control, Control>(textBox1, textBox2));
    }

    List<Tuple<Control, Control>> pairs = new List<Tuple<Control, Control>>();
    Point mDown = Point.Empty;

    private void Form2_Paint(object sender, PaintEventArgs e)
    {
        foreach (Tuple<Control, Control> cc in pairs)
            drawConnection(e.Graphics, cc.Item1, cc.Item2);
    }

    void drawConnection(Graphics G, Control c1, Control c2)
    {
        using (Pen pen = new Pen(Color.DeepSkyBlue, 3f) )
        {
            Point p1 = new Point(c1.Left + c1.Width / 2, c1.Top + c1.Height / 4);
            Point p2 = new Point(c2.Left + c2.Width / 2, c2.Top + c2.Height / 4);
            G.DrawLine(pen, p1, p2);
        }
    }

    void DragBox_MouseDown(object sender, MouseEventArgs e)
    {
        mDown = e.Location;
    }

    void DragBox_MouseMove(object sender, MouseEventArgs e)
    {
        TextBox tb = sender as TextBox;
        if (e.Button == MouseButtons.Left)
        {
            tb.Location = new Point(e.X + tb.Left - mDown.X, e.Y + tb.Top - mDown.Y);
        }
    }

    void DragBox_MouseUp(object sender, MouseEventArgs e)
    {
        mDown = Point.Empty;
    }

    private void DragBox_Move(object sender, EventArgs e)
    {
        this.Invalidate();
    }

}