Introduction
This is a class library that implements a user control that acts as a plug-in. This plug-in encapsulates basic drawing functionalities and exposes an interface to retrieve the drawing in the form of two dimensional coordinate values. The user can just drag and drop this component from the Toolbox to any control (Container type). Immediately after, it adds the capability of drawing basic graphical objects using mouse commands.
Background
The idea of developing this kind of a plug-in is to reduce the effort which comes every time a developer develops an application where he/she needs graphical drawing inputs from the user and has to do some processing over them. For example, an application to calculate the intersection of some polygons like circles, rectangles etc. Writing code every time to allow the user to draw objects and reflect them on the window will waste a lot of time of the developer. Using this component enables the developer to start his work on his own algorithms and not the drawing code.
Using the code
The code can be divided into these sections:
- Register for the events.
- Draw on the window Device Context and memory bitmap.
- Calculate the update region for each type of drawing.
- Modify parameters using right clicks.
1. Register for the events
The plug-in component registers the parent control event for drawing purposes.
this.Parent.MouseDown += new MouseEventHandler(Parent_MouseDown);
this.Parent.MouseMove += new MouseEventHandler(Parent_MouseMove);
this.Parent.MouseUp += new MouseEventHandler(Parent_MouseUp);
this.Parent.Paint += new PaintEventHandler(Parent_Paint);
2. Drawing on the window Device Context and memory bitmap
void DrawOnMem(Graphics g)
{
g.SmoothingMode = SmoothingMode.HighQuality;
Pen pen = new Pen(penColor, penWidth);
Brush brush = new SolidBrush(Color.FromArgb(127, brushColor));
if (startPoint != Point.Empty && endPoint != Point.Empty)
{
switch (drawType)
{
case type.LINE:
g.DrawLine(pen, startPoint, endPoint);
break;
case type.CIRCLE:
if (Fill.Checked)
g.FillEllipse(brush, Rectangle(startPoint, endPoint));
g.DrawEllipse(pen, Rectangle(startPoint, endPoint));
break;
case type.RECT:
if (Fill.Checked)
g.FillRectangle(brush, Rectangle(startPoint, endPoint));
g.DrawRectangle(pen, Rectangle(startPoint, endPoint));
break;
case type.FREEHAND:
g.DrawLine(pen, startPoint, endPoint);
break;
case type.NONE:
break;
default:
break;
}
}
pen.Dispose();
brush.Dispose();
}
3. Calculate the update region for each type of drawing
Calculating the optimum size region for each type of drawing is done to stop flickering during the drawing of objects. FindEnclosingRect
calculates the immediate outer region of a line.
private Region FindEnclosingRect(Point st,Point en)
{
double r = Math.Sqrt(Math.Pow((en.Y - st.Y), 2) + Math.Pow((en.X - st.X), 2));
Rectangle rc = new Rectangle(0, 0, (int)r, 0);
rc.Inflate((int)penWidth+1, (int)penWidth+1);
Region rgn = new Region(rc);
double m = (((double)en.Y - st.Y))/ (en.X - st.X);
double angle = Math.Atan(m);
if (en.X < st.X)
angle += 3.14;
Matrix mtrx = new Matrix();
mtrx.Reset();
mtrx.Rotate((float)(angle*180 * 7 / 22));
rgn.Transform(mtrx);
mtrx.Reset();
mtrx.Translate(st.X, st.Y);
rgn.Transform(mtrx);
return rgn;
}
There are some other functions as well, mainly calculates the bounding region of rectangles, circles, and lines, while the mouse move draws these objects on the window Device Context, and once the drawing finishes, stores the drawing in the memory device context.
Points of interest
If the developer wants the 2D coordinates of each drawing, then just uncomment the line which stores the coordinates in the arrays and read at runtime.
History
No updates..... till 07/01/2008.