0% found this document useful (0 votes)
185 views35 pages

T8-Basic Event Handling, Mapping Modes

The document discusses basic event handling, mapping modes, and scrolling views in MFC applications. It covers handling the WM_LBUTTONDOWN message by overriding the OnLButtonDown method. It also discusses different mapping modes like MM_TEXT, MM_HIMETRIC, MM_LOMETRIC, and variable scale mapping modes like MM_ISOTROPIC and MM_ANISOTROPIC. It provides examples of setting the window and viewport origins and extents to implement scrolling and scaling of drawings.

Uploaded by

michael.ferraris
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
185 views35 pages

T8-Basic Event Handling, Mapping Modes

The document discusses basic event handling, mapping modes, and scrolling views in MFC applications. It covers handling the WM_LBUTTONDOWN message by overriding the OnLButtonDown method. It also discusses different mapping modes like MM_TEXT, MM_HIMETRIC, MM_LOMETRIC, and variable scale mapping modes like MM_ISOTROPIC and MM_ANISOTROPIC. It provides examples of setting the window and viewport origins and extents to implement scrolling and scaling of drawings.

Uploaded by

michael.ferraris
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 35

Basic Event Handling, Mapping

Modes, and a Scrolling View

K. Vimala Devi
Sr. Lecturer
Dept. of CSE
AKCE – Kalasalingam University.
T8
Basic Event Handling, Mapping Modes,
and a Scrolling View

• The Message Handler:


void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
// event processing code here
}
The Message Map:
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_WM_LBUTTONDOWN()
// entry specifically for OnLButtonDown
// other message map entries
END_MESSAGE_MAP()
• Finally, your class header file needs the statement
DECLARE_MESSAGE_MAP()
Invalid Rectangle Theory
• InvalidateRect triggers a Windows WM_PAINT message, which is
mapped in the CView class to call to the virtual OnDraw function.

• If necessary, OnDraw can access the "invalid rectangle" parameter


that was passed to InvalidateRect.

• Your OnDraw function could call the CDC member function


GetClipBox to determine the invalid rectangle, and then it could
avoid drawing objects outside it.

• OnDraw is being called not only in response to your InvalidateRect


call but also when the user resizes or exposes the window.

• Thus, OnDraw is responsible for all drawing in a window, and it has


to adapt to whatever invalid rectangle it gets.
The Window's Client Area

The Window's Client Area


• A window has a rectangular client area that excludes the border, caption
bar, menu bar, and any toolbars.
• The CWnd member function GetClientRect supplies you with the client-area
dimensions.
• Normally, you're not allowed to draw outside the client area, and most
mouse messages are received only when the mouse cursor is in the client
area.
CRect, CPoint, and CSize Arithmetic
• The CRect, CPoint, and CSize classes are derived from the
Windows RECT, POINT, and SIZE structures, and thus they inherit
public integer data members as follows:
CRect left, top, right, bottom
CPoint x, y
CSize cx, cy
PtInRect

• Is a Point Inside a Rectangle?


• The CRect class has a member function PtInRect that
tests a point to see whether it falls inside a rectangle.

• The second OnLButtonDown parameter (point) is an


object of class CPoint that represents the cursor location
in the client area of the window. If you want to know
whether that point is inside the m_rectEllipse rectangle,
you can use PtInRect in this way:

if (m_rectEllipse.PtInRect(point))
{ // point is inside rectangle}
CRect LPCRECT Operator
• Notice that CWnd::InvalidateRect takes an LPCRECT parameter
(a pointer to a RECT structure), not a CRect parameter.

• A CRect parameter is allowed because the CRect class defines an


overloaded operator, LPCRECT(), that returns the address of a
CRect object, which is equivalent to the address of a RECT object.

• Thus, the compiler converts CRect arguments to LPCRECT


arguments when necessary. You call functions as though they had
CRect reference parameters. The view member function code

CRect rectClient;
GetClientRect(rectClient);

• retrieves the client rectangle coordinates and stores them in


rectClient.
Is a Point Inside an Ellipse?
• construct an object of class CRgn that corresponds to
the ellipse and then use the PtInRegion function instead
of PtInRect. Here's the code:

CRgn rgn;
rgn.CreateEllipticRgnIndirect(m_rectEllipse);
if (rgn.PtInRegion(point))
{ // point is inside ellipse}

• Note that the CreateEllipticRgnIndirect function is


another function that takes an LPCRECT parameter. It
builds a special region structure within Windows that
represents an elliptical region inside a window. That
structure is then attached to the C++ CRgn
EX04a - Basic Event Handling
Step 1:

• Using AppWizard and ClassWizard Together


• The following steps show how you use AppWizard and
ClassWizard together to create this application:

1.Run AppWizard to create EX04A. Use AppWizard to


generate an SDI project named EX04A in the
\vcpp32\ex04a subdirectory. The options and the
default class names are shown here.
EX04a - Basic Event Handling
Step 2:

• Add the m_rectEllipse and m_nColor data members


to CEx04aView. With the Workspace window set to
ClassView, right-click the CEx04aView class, select
Add Member Variable, and then insert the following
two data members:

private: CRect m_rectEllipse;


int m_nColor;

If you prefer, you could type the above code inside


the class declaration in the file ex04aView.h.
EX04a - Basic Event Handling
Step 3:
Use ClassWizard to add a CEx04aView class message handler.
• Choose ClassWizard from the View menu of Visual C++, or
right-click inside a source code window and choose
ClassWizard from the context menu.
• When the MFC ClassWizard dialog appears, be sure that the
CEx04aView class is selected, as shown in the illustration
below.
• Now click on CEx04aView at the top of the Object IDs list
box, and then scroll down past the virtual functions in the
Messages list box and double-click on
WM_LBUTTONDOWN.
• The OnLButtonDown function name should appear in the
Member Functions list box, and the message name should be
displayed in bold in the Messages list box. Here's the
ClassWizard dialog box.
Step 4:

• Edit the OnLButtonDown code in ex04aView.cpp. Click the Edit Code


button.
• ClassWizard opens an edit window for ex04aView.cpp in Visual C++
and positions the cursor on the newly generated OnLButtonDown
member function.
• The following boldface code (that you type in) replaces the previous
code:

void CEx04aView::OnLButtonDown(UINT nFlags, CPoint point)


{
if (m_rectEllipse.PtInRect(point))
{
if (m_nColor == GRAY_BRUSH)
{
m_nColor = WHITE_BRUSH;
}
else
{
m_nColor = GRAY_BRUSH;
}
InvalidateRect(m_rectEllipse);
}
}
Step 5:
• Edit the constructor and the OnDraw function in ex04aView.cpp.
• The following boldface code (that you type in) replaces the
previous code:

CEx04aView::CEx04aView() : m_rectEllipse(0, 0, 200, 200)


{
m_nColor = GRAY_BRUSH;
}

...

void CEx04aView::OnDraw(CDC* pDC)


{
pDC->SelectStockObject(m_nColor);
pDC->Ellipse(m_rectEllipse);
}
Step 6:

• Build and run the EX04A program. Choose


Build Ex04a.exe from the Build menu, or,
on the Build toolbar, click the button
shown here.
Mapping Modes

T8
Mapping Modes

•The device context has the default mapping mode, MM_TEXT,


assigned to it. The statement

• pDC->Rectangle(CRect(0, 0, 200, 200));

•Windows provides a number of other mapping modes, or


coordinate systems, that can be associated with the device context.

•Coordinates in the current mapping mode are called logical


coordinates.
If you assign the MM_HIMETRIC mapping mode, for example,
a logical unit is 1/100 millimeter (mm) instead of 1 pixel.

In the MM_HIMETRIC mapping mode, the y axis runs in the


opposite direction to that in the MM_TEXT mode: y values
decrease as you move down.

Thus, a 4-by-4-cm square is drawn in logical coordinates this


way:

pDC->Rectangle(CRect(0, 0, 4000, -4000));


The MM_TEXT Mapping Mode
•In MM_TEXT, coordinates map to pixels, values of x increase as you move right,
and values of y increase as you move down,

•But you're allowed to change the origin through calls to the CDC functions
SetViewportOrg and SetWindowOrg.

•Here's some code that sets the window origin to (100, 100) in logical coordinate
space and then draws a 200-by-200-pixel square offset by (100, 100).

•The logical point (100, 100) maps to the device point (0, 0). A scrolling window
uses this kind of transformation.

void CMyView::OnDraw(CDC* pDC)


{
pDC->SetMapMode(MM_TEXT);
pDC->SetWindowOrg(CPoint(100, 100));
pDC->Rectangle(CRect(100, 100, 300, 300));
}
The Fixed-Scale Mapping Modes
•One important group of Windows mapping modes provides fixed scaling

•In the MM_HIMETRIC mapping mode, x values increase as you move


right and y values decrease as you move down.

•The only difference among the fixed mapping modes is the actual scale
factor, listed in the table shown here.

Mapping Mode Logical Unit

MM_LOENGLISH 0.01 inch


MM_HIENGLISH 0.001 inch
MM_LOMETRIC 0.1 mm
MM_HIMETRIC 0.01 mm
MM_TWIPS 1
/1440 inch
The Variable-Scale Mapping Modes
 Windows provides two mapping modes, MM_ISOTROPIC and
MM_ANISOTROPIC, that allow you to change the scale factor as
well as the origin.

 With these mapping modes, your drawing can change size as the
user changes the size of the window.

 Also, if you invert the scale of one axis, you can "flip" an image
about the other axis and you can define your own arbitrary fixed-
scale factors.

 With the MM_ISOTROPIC mode, a 1:1 aspect ratio is always


preserved. In other words, a circle is always a circle as the scale
factor changes.

 With the MM_ANISOTROPIC mode, the x and y scale factors can


change independently. Circles can be squished into ellipses.
Here's an OnDraw function that draws an ellipse that fits exactly in its
window:

void CMyView::OnDraw(CDC* pDC)


{
CRect rectClient;  GetClientRect(rectClient);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(1000, 1000);
pDC->SetViewportExt(rectClient.right, -rectClient.bottom);
pDC->SetViewportOrg(rectClient.right / 2, rectClient.bottom / 2); 
 
pDC->Ellipse(CRect(-500, -500, 500, 500));
}

The functions SetWindowExt and SetViewportExt work together to set


the scale, based on the window's current client rectangle returned by the
GetClientRect function.
•The resulting window size is exactly 1000-by-1000 logical units.

•The SetViewportOrg function sets the origin to the center of the


window. Thus, a centered ellipse with a radius of 500 logical units fills
the window exactly.

•If you substitute MM_ISOTROPIC for MM_ANISOTROPIC in the


preceding example, the "ellipse" is always a circle

•It expands to fit the smallest dimension of the window rectangle.


The EX04B Example—Converting to the MM_HIMETRIC Mapping Mode

1. Use ClassWizard to override the virtual OnPrepareDC function.


ClassWizard can override virtual functions for selected MFC base classes,
including CView.

It generates the correct function prototype in the class's header file and a
skeleton function in the CPP file.

Select the class name CEx04aView in the Object IDs list, and then double-click
on the OnPrepareDC function in the Messages list. Edit the function as shown
here:

void CEx04aView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)


{
pDC->SetMapMode(MM_HIMETRIC);
CView::OnPrepareDC(pDC, pInfo);
}

The application framework calls the virtual OnPrepareDC function just


before it calls OnDraw.
2 Edit the view class constructor. You must change the
coordinate values for the ellipse rectangle. That rectangle is
now 4-by-4 centimeters instead of 200-by-200 pixels. Note
that the y value must be negative; otherwise, the ellipse will
be drawn on the "virtual screen" right above your monitor!

Change the values as shown here:

CEx04aView::CEx04aView() : m_rectEllipse(0, 0, 4000,


-4000)
{
m_nColor = GRAY_BRUSH;
}
3. Edit the OnLButtonDown function. This function must now convert the
ellipse rectangle to device coordinates in order to do the hit-test. Change
the function as shown in the following code:
void CEx04aView::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
OnPrepareDC(&dc);
CRect rectDevice = m_rectEllipse;
dc.LPtoDP(rectDevice);
if (rectDevice.PtInRect(point))
{
if (m_nColor == GRAY_BRUSH)
{ m_nColor = WHITE_BRUSH;
} else
{
m_nColor = GRAY_BRUSH;
}
InvalidateRect(rectDevice);
}}
4. Build and run the EX04B program. The output should look
similar to the output from EX04A, except that the ellipse size
will be different. If you try using Print Preview again, the
ellipse should appear much larger than it did in EX04A.
Device Context
The Device Context Classes

The Microsoft Windows device context is the key GDI element that represents a
physical device. Each C++ device context object has an associated Windows device
context, identified by a 32-bit handle of type HDC.

• The base class CDC has all the member functions (including some virtual functions)
that you'll need for drawing.

• If you (or the application framework) construct an object of a derived device context
class, you can pass a CDC pointer to a function such as OnDraw.

• For the display, the usual derived classes are CClientDC and CWindowDC. For other
devices, such as printers or memory buffers, you construct objects of the base class
CDC.

• It is easy to write code that works with both the printer and the display. A statement in
OnDraw such as

pDC->TextOut(0, 0, "Hello");

– sends text to the display, the printer, or the Print Preview window, depending on
the class of the object referenced by the CView::OnDraw function's pDC
parameter.
Constructing and Destroying CDC Objects

void CMyView::OnLButtonDown(UINT nFlags, CPoint point)


{
CRect rect;
CClientDC dc(this); // constructs dc on the stack
dc.GetClipBox(rect); // retrieves the clipping rectangle
} // dc automatically released

void CMyView::OnLButtonDown(UINT nFlags, CPoint point)


{
CRect rect;
CDC* pDC = GetDC();
// a pointer to an internal dc
pDC->GetClipBox(rect); // retrieves the clipping rectangle
ReleaseDC(pDC); // Don't forget this
}
The CPaintDC Class
• You'll need the CPaintDC class only if you override your view's OnPaint
function.

• The default OnPaint calls OnDraw with a properly set up device context,
but sometimes you'll need display-specific drawing code.

• The CPaintDC class is special because its constructor and destructor


do housekeeping unique to drawing to the display.

• Once you have a CDC pointer, however, you can use it as you would
any other device context pointer.

• Here's a sample OnPaint function that creates a CPaintDC object:

void CMyView::OnPaint()
{
CPaintDC dc(this);
OnPrepareDC(&dc);
dc.TextOut(0, 0, "for the display, not the printer");
OnDraw(&dc); // stuff that's common to display and printer
}
GDI Objects
Here's a list of the GDI derived classes:

• CBitmap—A bitmap is an array of bits in which one or more bits correspond to


each display pixel. You can use bitmaps to represent images, and you can use
them to create brushes.

• CBrush—A brush defines a bitmapped pattern of pixels that is used to fill areas
with color.

• CFont—A font is a complete collection of characters of a particular typeface


and a particular size. Fonts are generally stored on disk as resources, and
some are device-specific.

• CPalette—A palette is a color mapping interface that allows an application to


take full advantage of the color capability of an output device without
interfering with other applications.

• CPen—A pen is a tool for drawing lines and shape borders. You can specify a
pen's color and thickness and whether it draws solid, dotted, or dashed lines.

• CRgn—A region is an area whose shape is a polygon, an ellipse, or a


combination of polygons and ellipses. You can use regions for filling, clipping,
and mouse hit-testing.
Tracking GDI Objects

void CMyView::OnDraw(CDC* pDC)


{
CPen newPen(PS_DASHDOTDOT, 2,
(COLORREF) 0);
// black pen,
// 2 pixels wide
CPen* pOldPen = pDC->SelectObject(&newPen);
pDC->MoveTo(10, 10);
pDC->Lineto(110, 10);
pDC->SelectObject(pOldPen); // newPen is deselected
} // newPen automatically destroyed on exit
Stock GDI Objects
• The MFC library function CDC::SelectStockObject selects a stock
object into the device context and returns a pointer to the previously
selected object, which it deselects

void CMyView::OnDraw(CDC* pDC)


{
CPen newPen(PS_DASHDOTDOT, 2, (COLORREF) 0);
// black pen, // 2 pixels wide
pDC->SelectObject(&newPen);
pDC->MoveTo(10, 10);
pDC->Lineto(110, 10);
pDC->SelectStockObject(BLACK_PEN);
// newPen is deselected
} // newPen destroyed on exit

The Microsoft Foundation Class Reference lists, under


CDC::SelectStockObject, the stock objects available for pens,
brushes, fonts, and palettes.
Brush
void CEx3View::OnDraw(CDC* pDC)
{
CPaintDC d(this);
CBrush mybrush;
pDC->SelectStockObject(flag);
pDC->RoundRect(200,200,500,500,10,20);
mybrush.CreateSolidBrush(RGB(255,0,0));
pDC->SelectObject(&mybrush);
mybrush.DeleteObject ();
}
Thank you…

You might also like