t8-basic event handling, mapping modes

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

Upload: rajesh1158

Post on 18-Nov-2014

141 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: T8-Basic Event Handling, Mapping Modes

Basic Event Handling, Mapping Modes, and a Scrolling View

K. Vimala DeviSr. LecturerDept. of CSE

AKCE – Kalasalingam University. T8

Page 2: T8-Basic Event Handling, Mapping Modes

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()

Page 3: T8-Basic Event Handling, Mapping Modes

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.

Page 4: T8-Basic Event Handling, Mapping Modes

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

Page 5: T8-Basic Event Handling, Mapping Modes

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}

Page 6: T8-Basic Event Handling, Mapping Modes

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.

Page 7: T8-Basic Event Handling, Mapping Modes

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

Page 8: T8-Basic Event Handling, Mapping Modes

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.

Page 9: T8-Basic Event Handling, Mapping Modes
Page 10: T8-Basic Event Handling, Mapping Modes

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.

Page 11: T8-Basic Event Handling, Mapping Modes

EX04a - Basic Event HandlingStep 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.

Page 12: T8-Basic Event Handling, Mapping Modes
Page 13: T8-Basic Event Handling, Mapping Modes

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); } }

Page 14: T8-Basic Event Handling, Mapping Modes

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);

}

Page 15: T8-Basic Event Handling, Mapping Modes

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.

Page 16: T8-Basic Event Handling, Mapping Modes

Mapping Modes

T8

Page 17: T8-Basic Event Handling, Mapping Modes

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.

Page 18: T8-Basic Event Handling, Mapping Modes

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));

Page 19: T8-Basic Event Handling, Mapping Modes

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)); }

Page 20: T8-Basic Event Handling, Mapping Modes

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 inchMM_HIENGLISH 0.001 inchMM_LOMETRIC 0.1 mmMM_HIMETRIC 0.01 mmMM_TWIPS 1/1440 inch

Page 21: T8-Basic Event Handling, Mapping Modes

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.

Page 22: T8-Basic Event Handling, Mapping Modes

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.

 

Page 23: T8-Basic Event Handling, Mapping Modes

•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.

Page 24: T8-Basic Event Handling, Mapping Modes

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.

Page 25: T8-Basic Event Handling, Mapping Modes

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; }

Page 26: T8-Basic Event Handling, Mapping Modes

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);

} }

Page 27: T8-Basic Event Handling, Mapping Modes

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.

Page 28: T8-Basic Event Handling, Mapping Modes

Device ContextThe 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.

Page 29: T8-Basic Event Handling, Mapping Modes

Constructing and Destroying CDC Objects

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

CRect rect; CClientDC dc(this); // constructs dc on the stackdc.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 }

Page 30: T8-Basic Event Handling, Mapping Modes

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

}

Page 31: T8-Basic Event Handling, Mapping Modes

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.

Page 32: T8-Basic Event Handling, Mapping Modes

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

Page 33: T8-Basic Event Handling, Mapping Modes

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.

Page 34: T8-Basic Event Handling, Mapping Modes

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 ();}

Page 35: T8-Basic Event Handling, Mapping Modes

Thank you…