[Contents] [Prev] [Next]
Step 4: Drawing in the window
You can find the source for Step 4 in the file STEP04.CPP in the directory EXAMPLES\OWL\TUTORIAL. In this step, you'll add the ability to draw a line in the window by pressing the left mouse button and dragging. To do this, you'll add a two new events, WM_MOUSEMOVE and WM_LBUTTONUP, to the TDrawWindow response table, along with functions to handle those events. You'll also add a TClientDC * to the class.
Adding new events
To let the user draw on the window, the application must handle a number of events:
You need to add two macros to the window class' response table, EV_WM_MOUSEMOVE and EV_WM_LBUTTONUP. The new response table should look something like this:
DEFINE_RESPONSE_TABLE1(TDrawWindow, TWindow)
EV_WM_LBUTTONDOWN,
EV_WM_RBUTTONDOWN,
EV_WM_MOUSEMOVE,
EV_WM_LBUTTONUP,
END_RESPONSE_TABLE;
You also need to add the EvLButtonUp and EvMouseMove functions to the TDrawWindow class.
Adding a TClientDC pointer
The scheme used in Step 3 to draw a line isn't very robust:
You can take care of both of these problems rather easily by adding a new protected data member to TDrawWindow. This data member is a TDC * called DragDC. It works this way:
void
TDrawWindow::EvLButtonDown(uint, TPoint& point)
{
Invalidate();
if (!DragDC) {
SetCapture();
DragDC = new TClientDC(*this);
DragDC->MoveTo(point);
}
}
When the left mouse button is released, the EvLButtonUp function is called. If DragDC is valid (that is, if it represents a valid device context), EvLButtonUp deletes it, setting it to 0. The code for this function should look something like this:
void
TDrawWindow::EvLButtonUp(uint, TPoint&)
{
if (DragDC) {
ReleaseCapture();
delete DragDC;
DragDC = 0;
}
}
When the mouse is moved, the EvMouseMove function is called. This function checks whether the left mouse button is pressed by checking DragDC. If DragDC is 0, either the mouse button has not been pressed at all or it has been pressed and released. Either way, the user is not drawing, and the function returns. If DragDC is valid, meaning that the left mouse button is currently pressed down, the function draws a line from the current point to the new point using the TWindow::LineTo function.
void
TDrawWindow::EvMouseMove(uint, TPoint& point)
{
if (DragDC)
DragDC->LineTo(point);
}
Initializing DragDC
You must make sure that DragDC is set to 0 when you construct the TDrawWindow object:
TDrawWindow::TDrawWindow(TWindow *parent)
{
Init(parent, 0, 0);
DragDC = 0;
}
Cleaning up after DragDC
Because DragDC is a pointer to a TClientDC object, and not an actual TClientDC object, it isn't automatically destroyed when the TDrawWindow object is destroyed. You need to add a destructor to TDrawWindow to properly clean up. The only thing required is to call delete on DragDC. TDrawWindow should now look something like this:
class TDrawWindow : public TWindow
{
public:
TDrawWindow(TWindow *parent = 0);
~TDrawWindow() {delete DragDC;}
protected:
TDC *DragDC;
// Override member function of TWindow
bool CanClose();
// Message response functions
void EvLButtonDown(uint, TPoint&);
void EvRButtonDown(uint, TPoint&);
void EvMouseMove(uint, TPoint&);
void EvLButtonUp(uint, TPoint&);
DECLARE_RESPONSE_TABLE(TDrawWindow);
};
Note that, because the tutorial application has now become somewhat useful, the name of the main window has been changed from "Sample ObjectWindows Program" to "Drawing Pad":
SetMainWindow(new TFrameWindow(0, "Drawing Pad", new TDrawWindow));
Where to find more information
Here's a guide to where you can find more information on the topics introduced in this step:
[Contents] [Prev] [Next]