Introduction
Actually I am a little nervous to introduce this article. This is my first experience with MFC. Here I make a reusable class that is capable of drawing objects such as rectangle, ellipse, circle, and line by using GDI Device Context programming. The objects are selectable, moveable, and resizable. It is named CCanvas . I hope it will be useful for you. You can use it in your project that requires a simple graph editor.
Using the Code
Class Methods
Here are some public methods:
Hide Copy Code bool loadFile(char *fileName);
Loads a file.
Hide Copy Code bool saveFile(char *fileName);
Saves a file.
Hide Copy Code void set(CPoint ptStart, CPoint ptEnd);
Retrieves start and end position when mouse is dragged.
Hide Copy Code set(int tool);
Sets active tool: draw rectangle, draw ellipse, draw circle, or erase.
Hide Copy Code int update(CDC *dc);
Updates window.
Hide Copy Code void store();
Stores object into memory.
Hide Copy Code void drawGrid(CDC *dc, HWND hwnd, int gridsizeX, int gridsizeY)();
Draw grids within specified size.
Hide Copy Code void setSnapToGrid(bool setting, int gridsizeX, int gridsizeY);
Set snap-to-grid option within specified grid size.
How It Works
It works by handling these three important messages:
WM_LBUTTONDOWN - Start drawing, remember the origin position of the mouse pointer WM_MOUSEMOVE - Here it tracks mouse movement, remember its current position WM_LBUTTONUP - Finish drawing, store the newly created object into memory
How to Use
Let's say you have an SDI project, named Demo .
Add the file "canvas.h" to your DemoView.h:
Hide Copy Code #include "canvas.h"
Add these variables to your DemoView.h:
Hide Copy Code private:
CCanvas m_canvas;
CPoint m_ptStart;
CPoint m_ptEnd;
Add these window messages to your DemoView.cpp:
Hide Copy Code BEGIN_MESSAGE_MAP(CDemoView, CView)
//{{AFX_MSG_MAP(CDemoView)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
Add these codes to your DemoView.cpp to handle those window messages:
Hide Shrink Copy Code void CDemoView::OnDraw(CDC* dc)
{
CNiceDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
m_canvas.update(dc);
}
BOOL CDemoView::PreCreateWindow(CREATESTRUCT& cs)
{
m_canvas.setSnapToGrid(true, 10, 10);
return CView::PreCreateWindow(cs);
}
void CDemoView::OnMouseMove(UINT nFlags, CPoint point)
{
CView::OnMouseMove(nFlags, point);
// Update end point while mouse is moving
if (GetCapture() == this){
m_ptEnd = point;
Invalidate();
m_canvas.set(m_ptStart, m_ptEnd);
}
}
void CDemoView::OnLButtonDown(UINT nFlags, CPoint point)
{
CView::OnLButtonDown(nFlags, point);
// Get start point for drawing
m_ptStart = m_ptEnd = point;SetCapture();
m_canvas.set(m_ptStart, m_ptEnd);
}
void CDemoView::OnLButtonUp(UINT nFlags, CPoint point)
{
CView::OnLButtonUp(nFlags, point);
// Get end point for drawing
if (GetCapture() == this)
{
ReleaseCapture();
m_ptEnd = point;
Invalidate();
m_canvas.store();
}
}
Loading and Saving Documents
Function members for loading and saving documents are called in class CDemoDoc that exists in file DemoDoc.h and DemoDoc.cpp. It is a pretty long explanation. You can see it yourself in the demo source code. Basically it is simply a "how you deal with CDocument ."
Flickering Issue - Double Buffering
To get rid of the flickering issue, we can use the double buffering method. Look here. Follow the steps and you will see the flickering issue go away. The demo project attached with this article uses this method.
Points of Interest
This is my first MFC project and I am still improving it. I plan to add more features like:
- More object shapes
- Rotation
- Ordering (backward and forward)
- Select and move multiple objects
- Coloring
- Etc.
1st Update
I have fixed major bugs when creating vertical line. You cannot do anything to vertical line, it seems to be frozen. This is because of the incomplete mathematics equation I use in the code. I also added two new features: setSnapToGrid and drawGrid . I adapted code from Johan Rosengren for the drawGrid function. Don't worry, the rest is still original and kept to be as simple as it could be. Besides those things, now when you do resizing, the mouse cursor will change based on the resizing direction. The source is also converted to VC++ 2005. I think VC++6.0 has been abandoned.
History
- 31st January, 2009: Initial version
- 25th February, 2009: 1st update
|