Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

YaWhiteBoard - A Simple Whiteboard using C#

4.75/5 (8 votes)
14 Mar 2012CPOL3 min read 37.5K   2.2K  
A simple Whiteboard application

yaWhiteboard - Yet another whiteboard application

Creating Our Own Types

We know that the whiteboard application will have two modes, i.e., Write mode and Erase mode so we go ahead and create an enum to keep track of the current mode.

C#
enum MODE
{
    WRITE,
    ERASE
};

Now the way we are going to achieve the drawing functionality is:

  1. Get the position where user clicked the mouse down (say point1)
  2. Check for mouse movement
  3. If mouse is moved, then get the new mouse position (say point2)
  4. Draw a line from point1 to point2
  5. Now this new position will become the old position because user will eventually move the mouse further (i.e., point1 = point2)
  6. Keep doing all the above steps till user releases the mouse.

So we now create a small struct for holding the Line data:

C#
struct Line
{
    public Pen pen;
    public Point p1;
    public Point p2;

    public Line(Pen p, Point one, Point two)
    {
        pen = p;
        p1 = one;
        p2 = two;
    }
}

This Line keeps track of the terminal points of the line and the Pen which was used to draw this line (since Pen contains Color & Width information for the Line).

Tracking the Mouse Down and Up Events

The way we do this is to have a member variable to remember the state and handing the Mouse_down and Mouse_Up Events of the SplitContainers's Panel. Also, since we are planning to keep track of mouse position when the mouse is pressed or released, we need to keep track of the mouse position too in these events.

C#
bool isPressed = false;
//these are X n Y coordinates of point1 in our algorithm
int x1;
int y1;

private void splitContainer1_Panel2_MouseUp(object sender, MouseEventArgs e)
{
    x1 = e.X;
    y1 = e.Y;

    isPressed = false;
}

private void splitContainer1_Panel2_MouseDown(object sender, MouseEventArgs e)
{
    x1 = e.X;
    y1 = e.Y;

    isPressed = true;
}

Now when the mouse is moved, we need to draw the line and update the points which will be done in Mouse_Move event.

C#
//These coordinates are for "point2" of our algorithm
int x2;
int y2;

private void splitContainer1_Panel2_MouseMove(object sender, MouseEventArgs e)
{
    if (isPressed == true)
    {
        x2 = e.X;
        y2 = e.Y;

        Line line = new Line(CurrentPen, new Point(x1, y1), new Point(x2, y2));
        g.DrawLine(line.pen, line.p1, line.p2);

        x1 = x2;
        y1 = y2;
    }
}

The code above shows CurrentPen is being to draw the line. This variable will actually be updated based on users selection of markers. If the user selects a marker, it will return a marker of appropriate color and if user selects eraser, it will return a Pen of white color (effectively an eraser). The implementation details are shown below. (Refer to the source code for details.)

C#
pen = new Pen(Color.Blue, 2.0f);
eraser = new Pen(Color.White, 100.0f);

private Color CurrentColor
{
    get { return pen.Color; }
    set { pen.Color = value; }
}

private Pen CurrentPen
{
    get
    {
        if (mode == MODE.WRITE)
        {
            return pen;
        }
        else
        {
            return eraser;
        }
    }
}

The Problem

We are now almost done with the main functionality as we are drawing on the board with either marker or eraser. But there is a small problem. The problem is when our application goes out of focus, i.e., if user minimizes it or does an alt-tab, the drawings on our board will go away. To persist the drawing in such conditions, we need to:

  1. Remember the drawings on the board (this will change our Mouse_Move method)
  2. Override the Paint method and redraw everything in it.

So let us have a list that keeps track of whatever we drew so far.

C#
List<Line> lines = null;

private void splitContainer1_Panel2_MouseMove(object sender, MouseEventArgs e)
{
    if (isPressed == true)
    {
        x2 = e.X;
        y2 = e.Y;

        Line line = new Line(CurrentPen, new Point(x1, y1), new Point(x2, y2));
        g.DrawLine(line.pen, line.p1, line.p2);

        lines.Add(line);  //this will help to remember all the lines we drew so far

        x1 = x2;
        y1 = y2;
    }
}

And then, we just have to redraw everything in the overridden Paint method.

C#
private void splitContainer1_Panel2_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;

    foreach (Line l in lines)
    {
        g.DrawLine(l.pen, l.p1, l.p2);
    }
}

And that's it, we have a rudimentary implementation of whiteboard in place. This is not the most elegant way to do it, but it is one way to do it.

History

  • 8th February, 2012: First implementation of a rudimentary white board
  • 9th February, 2012: Updated to use all colors and choose custom marker size (as suggested in the comments)
  • 10th February, 2012: Minor changes in user interface, removed the annoying radio button
  • 14th March, 2012: Fixed the bug where drawing colors are getting changed on repaint

License

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