Click here to Skip to main content
15,880,905 members
Articles / Programming Languages / C#
Article

Canvas implementation for C#

Rate me:
Please Sign up or sign in to vote.
4.43/5 (29 votes)
21 Mar 20044 min read 255.5K   9.6K   118   45
Design and implementation of canvas in C#

Image 1

Introduction

In many different applications, graphical input is needed. Along with creating new graphical objects such as lines, rectangles and polygons, objects editing and viewing in different scale are required. In some cases, graphics events such as shape creation, selection and moving should be bound to some application logic.

Canvas or graphical editor is a component that provides an application with such functionality.

Background

Canvas control or widget is a component containing different types of graphical objects responsible for its viewing and editing.

Most of the GUI toolkits have their own canvas components. For example, there are canvases in Qt toolkit, Borland C++ Builder and Tcl/Tk. Somehow, it’s missing in .NET.

For canvas implementation and functionality, I use my experience with Qt and Tcl/Tk toolkits. In both toolkits, canvas provides rich functionality to create and manipulate graphical objects.

In both toolkits, scaling and translating of canvas affects geometry of graphical objects stored inside. It’s inconvenient when you're storing “real world“ measurements in your canvas, so each time you edit it in the canvas, you should keep track on changes of the “real world” coordinate system.

To avoid this inconvenience, this implementation is logically divided to geometrical model and view. When you're editing objects inside the canvas, geometrical model (presented in “real world” coordinates) is changing and the view (client coordinates) stays the same, and when you rescale and scroll the canvas, the geometrical model stays unchanged.

Canvas geometrical model could have several views showing different parts of the model. All views are updated automatically when the model changes, it means that if you moving or editing shape in one of the views you will see changes in others.

Using canvas

Canvas is implemented in Canvas.cs file in CanvasControl namespace.

Example how to use it is in CanvasDemo.cs file.

To create a new Canvas and connect to its events:

C#
// create new canvas
canvas1 = new CanvasControl.Canvas();
// connect listeners to canvas events
canvas1.CoordChangeEvent += new
  CanvasControl.Canvas.CoordChangeEventHandler(OnCoordChainged);
canvas1.ItemNewEvent += new
  CanvasControl.Canvas.ItemEventHandler(OnNewCanvasItem);
canvas1.ItemEnterEvent += new
  CanvasControl.Canvas.ItemEventHandler(OnEnterCanvasItem);

where:

CoordChangeEvent event is generated when cursor moves inside the Canvas. A second parameter of the event handler CoordChangeEventHandler contains coordinates of the cursor and R,G,B values of the background image.

C#
public void OnCoordChainged(object sender, 
CanvasControl.CoordEventArgs e)
{
    textBox1.Text = e.X.ToString() + "," + e.Y.ToString();
}

ItemNewEvent and ItemEnterEvent – events are generated when cursor enters and leaves graphical object. The second parameter contains ID (index) of the object. Graphical object could be accessed by its ID.

C#
public void OnEnterCanvasItem(object sender, 
CanvasControl.ItemEventArgs e)
{
    textBox3.Text = e.indx.ToString();
}

In order to create additional view of existing Canvas (its geometrical model) we should create second Canvas, say canvas2 and attach it to previous one:

C#
canvas2 = new CanvasControl.Canvas();
canvas2.setGeomModel(canvas1.getGeomModel());

Canvas itself does not contain other graphical controls, it’s controlled by its API. But there is an option to connect Scrollbar controls to update scrollbars controls during canvas navigation.

C#
canvas1.connectScrolls(hScrollBar1,vScrollBar1);

To create, move or select graphical objects, we need to change Canvas state as follows:

C#
// create graphical objects
canvas1.CreateRectangle();

canvas1.CreateLine();

canvas1.CreatePolygon();

// move objects
canvas1.StartMoving();
// select objects
canvas1.StartSelection();

Graphical object could be accessed by its ID and geometrical and other properties could be retrieved or updated. In the function bellow, ID-s of selected items are retrieved and updated with user defined color.

C#
private void btnColor_Click(object sender, System.EventArgs 
e)
{
        ColorDialog colorDialog = new ColorDialog();
        if(colorDialog.ShowDialog() != DialogResult.OK)
                 return;

        Color color = colorDialog.Color;
        int [] selected = canvas1.GetSelected();
        foreach(int i in selected)
        {
                 CanvasControl.CanvasItem item = canvas1.GetItem(i);
                 item.Icolor = color;
                 item.select(false);
        }

        canvas1.Invalidate();
        canvas1.Update();
}

You can create your own geometrical object, to do it, you should implement CanvasItem interface (see Canvas.cs file) and use Canvas.AddShape method to put it into the canvas.

Design issues

Several design patterns are used in the design of the canvas.

Template pattern is used in CanvasItem class to implement some shapes common functionality in the base class.

Observer pattern is used to notify subscribers about canvas changes, it's implemented using C# events.

Facade pattern is used to hide internal canvas objects from the user.

Image 2

In the class diagram above classes creating canvas contol are presented

  • Canvas - encapsulates view of the canvas control (Model/View pattern). Canvas is syncronized with geometrical model CanvasGeomModelvia C# events. Every time the model had changed the model generates ItemChangedEvent or ModelChangedEvent forcing canvas update the view. Each time the view Canvas needs to display the model, it calls draw method of CanvasGeomModel specifying graphical context (or painter object) Graphics and a Matrix transformaion between "client" coordinate system of view and "real world" coordinate system of the model. Eventually from CanvasGeomModel draw request is delegated to concreat shapes, which implement CanvasItem draw interface to draw itself on the view.
  • CanvasGeomModel - encapsulates geometrical model of the canvas control. It is responsable for storing, editing and displaying of different shapes, derived from CanvasItem class. Geometrical objects are represented in the model in "real world" coordinates independently from "client" coordinates of different views.
  • CanvasItem - encapsulates common behavior of geometrical objects or shapes stored in geometrical model CanvasGeomModel. It represents interface using by Canvas to manipulate and display differents types of shapes. In order to create new shape one should implement methods defined in CanvasItem interface.
    C#
    public class LineCanvasItem : CanvasItem
    {
      public float x1;
      public float y1;
      public float x2;
      public float y2;
      private bool is_selected = false;
    
      // construct from 2 points coordinates
      public LineCanvasItem(float x_1,float y_1,float x_2,float y_2)
      {
        x1 = x_1;
        y1 = y_1;
        x2 = x_2;
        y2 = y_2;
      }
      // returns true if item is selected
      public override bool isSelected()
      {
        return is_selected;
      }
      // select item
      public override void select(bool m)
      {
        is_selected = m;
      }
      // returns true if the item is within the distanse
      public override bool isCloseToPoint(PointF pnt,float dist)
      {
        double curr_dist = Geom.segmentToPointSqrDist(
          new PointF(x1,y1),new PointF(x2,y2),pnt);
    
        return Math.Sqrt(curr_dist) < dist;
      }
      // return bounding box of the item
      public override RectangleF boundingBox()
      {
        return new RectangleF(x1,y1,x2-x1,y2-y1);
      }
      // start point X coordinate of the shape
      public override float X()
      {
        return x1;
      }
      // start point Y coordinate of the shape
      public override float Y()
      {
        return y1;
      }
      // move shape to specified location
      public override void move(PointF p)
      {
        float dx = p.X-x1;
        float dy = p.Y-y1;
    
        x1 += dx;
        y1 += dy;
    
        x2 += dx;
        y2 += dy;
      }
      // move shape by specified shift
      public override void moveBy(float xs,float ys)
      {
        x1+=xs;
        y1+=ys;
    
        x2+=xs;
        y2+=ys;
      }
      // draw shape on the view
      public override void draw(Graphics graph,
          System.Drawing.Drawing2D.Matrix trans)
      {
        // transform points to "client" view coordinate system
        PointF [] points = {new PointF(x1,y1), new PointF(x2,y2)};
        trans.TransformPoints(points);
    
        // draw line in "client" coordinate system
        if(is_selected)
          graph.DrawLine(new Pen(Color.Cyan),
            (int)points[0].X,(int)points[0].Y,
            (int)points[1].X,(int)points[1].Y);
        else
          graph.DrawLine(new Pen(Icolor),(int)points[0].X,
            (int)points[0].Y,
            (int)points[1].X,(int)points[1].Y);
      }
    }
    
    Then Canvas.AddShape method should be used to add new shape to the canvas:
    C#
    canvas1.AddShape(new LineCanvasItem(10,10,100,100));
    
  • Geom - Geometrical procedures used in Canvas.

History

  • 28/02/2004 Initial version.
  • 17/03/2004 Geometrical model separated from canvas view + design explanations.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Canada Canada
Baranovsky Eduard has been a software developer for more then 10 years. He has an experence in image processing, computer graphics and distributed systems design.

Comments and Discussions

 
GeneralText selectable &amp; Arc implementation Pin
pxp13-Aug-04 14:08
pxp13-Aug-04 14:08 
GeneralRe: Text selectable &amp; Arc implementation Pin
Eduard Baranovsky18-Aug-04 3:01
Eduard Baranovsky18-Aug-04 3:01 
GeneralRe: Text selectable &amp; Arc implementation Pin
pxp18-Aug-04 3:14
pxp18-Aug-04 3:14 
GeneralRe: Text selectable &amp; Arc implementation Pin
Eduard Baranovsky19-Aug-04 3:57
Eduard Baranovsky19-Aug-04 3:57 
GeneralRe: Text selectable &amp; Arc implementation Pin
pxp19-Aug-04 12:42
pxp19-Aug-04 12:42 
QuestionText on this Canvas? Pin
Clinton Pierce23-Apr-04 8:20
Clinton Pierce23-Apr-04 8:20 
AnswerRe: Text on this Canvas? Pin
Eduard Baranovsky26-Apr-04 6:05
Eduard Baranovsky26-Apr-04 6:05 
QuestionCan you use this for a tennis court? Pin
NicoVB30-Mar-04 5:36
NicoVB30-Mar-04 5:36 
Hi, i'm building an app to analyze tennis matches... can i use this to for example measure speed of the ball???

thanks

nico

http://www.nico.gotdns.com
AnswerRe: Can you use this for a tennis court? Pin
Eduard Baranovsky31-Mar-04 9:42
Eduard Baranovsky31-Mar-04 9:42 
QuestionAdding a bitmap item to the canvas? Pin
Elwood15117-Mar-04 9:41
Elwood15117-Mar-04 9:41 
AnswerRe: Adding a bitmap item to the canvas? Pin
Eduard Baranovsky18-Mar-04 4:09
Eduard Baranovsky18-Mar-04 4:09 
GeneralRe: Adding a bitmap item to the canvas? Pin
Elwood15118-Mar-04 6:48
Elwood15118-Mar-04 6:48 
GeneralCanvas need Help...Plz Pin
thoppil14-Mar-04 19:41
thoppil14-Mar-04 19:41 
GeneralRe: Canvas need Help...Plz Pin
Eduard Baranovsky15-Mar-04 8:49
Eduard Baranovsky15-Mar-04 8:49 
GeneralAnother Canvas, in VG.net Pin
Frank Hileman2-Mar-04 5:51
Frank Hileman2-Mar-04 5:51 
GeneralRe: Another Canvas, in VG.net - yet another Pin
Paul Selormey22-Mar-04 14:45
Paul Selormey22-Mar-04 14:45 
GeneralRe: Another Canvas, in VG.net - yet another Pin
Southmountain12-Aug-22 16:37
Southmountain12-Aug-22 16:37 
QuestionWhat is Canvas? Pin
Paul Selormey29-Feb-04 3:29
Paul Selormey29-Feb-04 3:29 
AnswerRe: What is Canvas? Pin
Jörgen Sigvardsson29-Feb-04 4:28
Jörgen Sigvardsson29-Feb-04 4:28 
GeneralRe: What is Canvas? Pin
Paul Selormey29-Feb-04 5:12
Paul Selormey29-Feb-04 5:12 
GeneralRe: What is Canvas? Pin
Jörgen Sigvardsson29-Feb-04 5:23
Jörgen Sigvardsson29-Feb-04 5:23 
AnswerRe: What is Canvas? Pin
Eduard Baranovsky1-Mar-04 4:05
Eduard Baranovsky1-Mar-04 4:05 
GeneralRe: What is Canvas? Pin
Paul Selormey2-Mar-04 4:24
Paul Selormey2-Mar-04 4:24 
AnswerRe: What is Canvas? Pin
darkbyte3-Mar-04 4:13
darkbyte3-Mar-04 4:13 
GeneralRe: What is Canvas? Pin
Paul Selormey3-Mar-04 4:25
Paul Selormey3-Mar-04 4:25 

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.