Using the new MFC7/ATL7 shared classes.






4.64/5 (4 votes)
May 13, 2001
2 min read

66588

499
This example demonstrates using the new shared ATL/MFC classes such as CPoint, CRect, CSize and CString
Introduction
Beginning with Visual C++ .NET 7.0, CPoint
, CRect
, CSize
, CString
, CImage
classes have been written to be library-independent. These classes can be
used in either MFC or ATL projects, or in projects that do not use either
of these libraries.
This article presents an application called SharedClasses that is a Win32 Project generated by the AppWizard. The application handles mouse input and draws an ellipse based on the mouse movement. The shared MFC/ATL classes are used throughout the application.
The demo app
To draw the ellipse press the left mouse button (it will be the center of the ellipse) and move the mouse while holding the button. The status line at the top of the window shows the center coordinates and the ellipse's dimension (width and height).
The AppWizard generate an application that implements simple window. To add new functionality we have to modify window the procedure (WndProc) function.
We will be using the CString
and CRect
classes, so to add support for it
we need to include the following headers:
#include <atltypes.h> // CPoint, CRect, CSize support. #include <atlstr.h> // CString support.
we also need to include Windowsx.h to use GET_X_LPARAM
and GET_Y_LPARAM
macros.
#include <Windowsx.h> // GET_X_LPARAM and GET_Y_LPARAM defined there.
To track mouse input let's add a CRect
type variable.
CRect rectEllipse; // Rectangle to track mouse movement.
To keep status line text we use a CString
class.
CString strCoord; // String to print ellipse coordinates and dimensions.
We also need a flag to keep the state of the left mouse button.
bool bLBtnPressed = false; // Flag to keep left mouse button state.
To track the mouse input we handle three windows messages: WM_LBUTTONDOWN
, WM_LBUTTONUP
, and WM_MOUSEMOVE
.
Just add following code to the end of switch statement inside WndProc
, just
before the default label:
case WM_LBUTTONDOWN: // Save beginning point. rectEllipse.left = GET_X_LPARAM(lParam); rectEllipse.top = GET_Y_LPARAM(lParam); // Set flag that keeps mouse button state. bLBtnPressed = true; // Capture mouse input. ::SetCapture(hWnd); break; case WM_LBUTTONUP: // Reset flag that keeps mouse button state. bLBtnPressed = false; // Release mouse input. ::ReleaseCapture(); // Redraw window. ::InvalidateRect(hWnd, NULL, TRUE); ::UpdateWindow(hWnd); break; case WM_MOUSEMOVE: // If mouse button is pressed update rectangle that // tracks mouse movement with new coordinates, // and redraw window. if(bLBtnPressed) { rectEllipse.right = GET_X_LPARAM(lParam); rectEllipse.bottom = GET_Y_LPARAM(lParam); ::InvalidateRect(hWnd, NULL, TRUE); ::UpdateWindow(hWnd); } break;
In the WM_LBUTTONDOWN
message handler we store the coordinates of the point
where the user pressed the left mouse button. This will be the center of our
ellipse. We set the flag that stores mouse button state and capture the mouse
input so as to handle mouse input even when it is outside the window.
The WM_MOUSEMOVE
message handler checks the state of the mouse button. If it
is pressed it updates our rectangle (our CRect
class object) with the new mouse
coordinates and redraws the window. If the mouse button is not pressed, it does
nothing.
In the WM_LBUTTONUP
handler we just update the flag that keeps the mouse button
state and release the mouse capture. Inside it just draws the ellipse according
to the coordinates stored in the CRect
object and formats and prints a status
string to show information for the ellipse, namely center coordinates and dimensions.
In order to draw our ellipse we have to modify WM_PAINT
message handler:
// Draw the ellipse using coordinates from mouse input. ::Ellipse( hdc, rectEllipse.left - rectEllipse.Width(), rectEllipse.top - rectEllipse.Height(), rectEllipse.left + rectEllipse.Width(), rectEllipse.top + rectEllipse.Height()); // If ellipse is not a dot or line, print center coordinates // and dimensions. Otherwise print prompt to draw ellipse. if(rectEllipse.Width() != 0 && rectEllipse.Height() != 0) { strCoord.Format(_T("Center coordinates %d,%d X-size %d, Y-Size %d"), rectEllipse.left, rectEllipse.top, 2 * rectEllipse.Width(), 2 * rectEllipse.Height()); } else strCoord = _T("Use your mouse to draw ellipse in the window"); ::TextOut(hdc, 5, 5 , strCoord, strCoord.GetLength());
History
16 Oct 2001 - updated files for VS beta 2