Click here to Skip to main content
15,559,459 members
Articles / Programming Languages / C#
Tip/Trick
Posted 27 Apr 2012

Stats

30.5K views
1.4K downloads
15 bookmarked

A simple example of adding movable label controls at runtime

Rate me:
Please Sign up or sign in to vote.
4.44/5 (4 votes)
23 Jan 2013CPOL
I created a simple form with a button to add a label control at run time sequentially numbered; labels are movable and lines are drawn between labels.

Introduction

This is my first article, I intended it for beginners like me in C# as an example.

The code attached is an example of assigning events at run time and using delegates. It is simple and sheds light on the ideas used in graphics programs used by engineers. This code could be enhanced by adding rotation functionality around three dimensional axes.

Detail

The image below shows the screen with some labels added and moved from their initial places by mouse and lines are drawn between them.

Image 1

Using the code

In this sample I created a simple form with a button to add a label control at run time sequentially numbered. When adding each label I assign to it labelMouseDown and labelMouseMove events. I use these two methods to draw lines connecting the added labels. The lines drawn have two modes, either only one line is drawn from the last added label to the previous one, or the "LinkToAll" mode, where a line is drawn to each existing label.

C#
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace MovableLabels
{
    public partial class Form1 : Form
    {        
        Label[] lblArray;  // an array to hold all added controls 
        Point move;        
        // drawing variables
        Graphics g;
        Pen green = new Pen(Color.Green, 2);
        // position
        int lblNum = 0;
        const int Horizontal = 50;
        int Vertical = 0;
        // delegate
        delegate void callDrawDel();
        callDrawDel callDraw;
        public Form1()
        {
            InitializeComponent();
            g = this.CreateGraphics();
            callDraw = drawLines;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            // Create the label and define its initial locatio
            Label o = new Label();
            o.Visible = true;
            o.Top = Vertical*lblNum ;
            Vertical += 10;
            o.Left = Horizontal * lblNum;
            o.Text = (++lblNum).ToString();
            o.AutoSize = true;         
            // assign moving related methods
            o.MouseDown += new MouseEventHandler(this.labelMouseDown);
            o.MouseMove += new MouseEventHandler(this.labelMouseMove);
            // add to the screen
            this.Controls.Add(o);
            List<Label> lblList = new List<Label>();
            foreach (Control c in Controls)
                if (c is Label)
                    lblList.Add((Label)c);
            lblArray = lblList.ToArray();  
        
            // draw lines
            callDraw();    // using delegate
        }
        private void labelMouseDown(object sender, MouseEventArgs e)
        {
            move = e.Location;
        }
        
        // the method do the actual label moving
        private void labelMouseMove(object sender, MouseEventArgs e)
        {
            // cast the sender object to a control to access the Left and Top properties
            Control o = (Control)sender;
            if (e.Button == MouseButtons.Left)
            {                
                o.Left += e.X - move.X;
                o.Top += e.Y - move.Y;
                callDraw();
            }
        }
        // The methods drawLines and drawLinesAll are just examples of drawing lines in varied forms
        // An enormous number of methods could be invented to connect lines resulting in very glorious 
        // shapes
        // The check box could be changed to a list box to show methods as you wish
        
        private void drawLines()
        {
            g.Clear(this.BackColor);
            for (int i = 1; i < lblArray.Length; i++)
                lineDraw(lblArray[i - 1], lblArray[i]);
        }
        private void drawLinesAll()
        {
            g.Clear(this.BackColor);
            for (int k = 0; k < lblArray.Length; k++)
            {
                Label L1 = lblArray[k];
                for (int j = k + 1; j < lblArray.Length; j++)                    
                    lineDraw(L1, lblArray[j]);
            }
        }
        private void lineDraw(Label L1, Label L2)
        {
            // define the starting & ending point 
            int x1, x2, y1, y2;
            // starting point from the center of the first label L1
            x1 = L1.Location.X + L1.Width / 2;
            y1 = L1.Location.Y + L1.Height / 2;
            // starting point from the center of the second label L2
            x2 = L2.Location.X + L2.Width / 2;
            y2 = L2.Location.Y + L2.Height / 2;
            g.DrawLine(green, x1, y1, x2, y2);
        }
        private void LinkToAll_CheckedChanged(object sender, EventArgs e)
        {
            // decide what method to call
            bool chk = LinkToAll.CheckState == CheckState.Checked;
            if (chk) 
                 callDraw = drawLinesAll; 
            else callDraw = drawLines;
            // then call it via delegate type
            callDraw();
        }
        private void btnClear_Click(object sender, EventArgs e)
        {
            // remove all labels using the array lblArray
            foreach (Control c in lblArray)
              this.Controls.Remove(c);
            g.Clear(this.BackColor);
            lblNum = Vertical = 0;
        }
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Egypt Egypt
I am an ERP developer using VFP9
I started as a Clipper 5.2 with DBase III+ in 1995, I worked with Access 2.0
Then I converted to VFP5.0 then VFP9, I worked on an ERP application written by FoxPro2.6

Recently, I started learning C#
I have a tendency to do generic work and build generic functions, I try to do that using C#

I'm preparing myself now to be a Framework C# programmer
First step I'll read the C# specification, when done I'll update this, I've already started this in Feb-27-2013

Comments and Discussions

 
SuggestionSuggestion Pin
intrueder23-Jan-13 11:59
intrueder23-Jan-13 11:59 
GeneralRe: Suggestion Pin
Tarek Elqusi24-Jan-13 5:06
professionalTarek Elqusi24-Jan-13 5:06 
SuggestionExplanations Pin
Wendelius28-Dec-12 10:38
mveWendelius28-Dec-12 10:38 
GeneralRe: Explanations Pin
Tarek Elqusi5-Jan-13 1:44
professionalTarek Elqusi5-Jan-13 1:44 
GeneralRe: Explanations Pin
Wendelius6-Jan-13 6:02
mveWendelius6-Jan-13 6:02 
QuestionMy vote of 3 Pin
Dave Kreskowiak27-Dec-12 12:53
mveDave Kreskowiak27-Dec-12 12:53 
AnswerRe: My vote of 3 Pin
Tarek Elqusi5-Jan-13 1:54
professionalTarek Elqusi5-Jan-13 1:54 
GeneralRe: My vote of 3 Pin
Dave Kreskowiak5-Jan-13 8:12
mveDave Kreskowiak5-Jan-13 8:12 
GeneralMy vote of 5 Pin
member6027-Apr-12 23:15
member6027-Apr-12 23:15 
My 5!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.