Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用文本框绘制线条_C#_Drawing_Lines - Fatal编程技术网

C# 用文本框绘制线条

C# 用文本框绘制线条,c#,drawing,lines,C#,Drawing,Lines,我有一个应用程序,我可以在屏幕上添加一个文本框并移动它。 当我添加两个以上的文本框时,我双击两个文本框的顶部,一条线将两者连接起来 我的问题是:如何使行与文本框一起移动? 代码如下: public partial class principal : Form { int posMouseFormX, posMouseFormY; int posMouseTXT_X, posMouseTXT_Y; int posActTXT_X, posActTXT_Y; bool

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

我的问题是:如何使行与文本框一起移动? 代码如下:

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();
        }
    }
}
每个控件(包括文本框)都有一个移动、事件。在那里打一个无效的电话

线条应该在包含文本框(可能是表单)的容器的绘制事件中绘制;如果它确实是表单,请调用此.Invalidate

请将线条绘制代码从双击事件移到绘制事件中,否则当系统必须重新绘制应用程序时,线条将不会持续,例如最小化/最大化事件或其他情况

您可能需要创建一个数据结构来维护关于哪些文本框对需要连接的信息,可能是一个列表或一个列表。这将在双击事件中填充/修改,然后调用This.Invalidate和Form.Paint。在文本框对列表上有一个foreach循环

如果您在表单上绘图,请确保打开双缓冲

更新:要比较reults,这里有一个最小的示例,表单上需要两个文本框:


嗨,谢谢。你帮了我很多。我可以用连接线移动文本框!唯一的问题是,当我移动时,线在闪烁。你有办法解决这个问题吗?我已经激活了双缓冲。你是在窗体上还是在面板等其他控件上绘图。。?画了多少条线?我在表格上画。例如,当我只插入与文本框关联的两行并移动文本框时,它们在移动文本框时闪烁。我添加了一个最小的示例。我看到文本框需要一点时间才能移动,但行不会闪烁。
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();
    }

}