Chapter 17 Creating the Document and Improving the View

Slides:



Advertisements
Similar presentations
Introduction to Macromedia Director 8.5 – Lingo
Advertisements

Computer Basics Hit List of Items to Talk About ● What and when to use left, right, middle, double and triple click? What and when to use left, right,
Using Macros and Visual Basic for Applications (VBA) with Excel
XP Tutorial 4 New Perspectives on Microsoft Windows XP 1 Microsoft Windows XP Personalizing Your Windows Environment Tutorial 4.
Using the Visual Basic Editor Visual Basic for Applications 1.
Microsoft Visual Basic 2005 CHAPTER 8 Using Procedures and Exception Handling.
Chapter 8: String Manipulation
Working with Numbers in Alice - Converting to integers and to strings - Rounding numbers. - Truncating Numbers Samantha Huerta under the direction of Professor.
Hello World In C++ and Microsoft Visual C++. Directions to begin a project 1. Go to All Programs 2. Open Visual Studio C++ 3. Click on New Project 4.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 19 Clicker Questions November 3, 2009.
Microsoft Visual Basic 2012 Using Procedures and Exception Handling CHAPTER SEVEN.
Bertrand Bellenot ROOT Users Workshop Mar ROOT GUI Builder Status & Plans ROOT & External GUI World MFC, FOX, Qt, PVSS… Snapshot of the Future.
1 Chapter 15 Drawing in a Window. 2 The Window Client Area  A coordinate system that is local to the window.  It always uses the upper-left corner of.
Visual C++ Lecture 11 Friday, 29 Aug Windows Graphic User Interface l Event driven programming environment l Windows graphic libraries (X11 on Unix,
Chapter 5 Menus, Common Dialog Boxes, and Methods Programming in C#.NET © 2003 by The McGraw-Hill Companies, Inc. All rights reserved.
MFC Windows Programming: Document/View Approach More detailed notes at: 360/notes-html/class15.htm.
1. Chapter 4 Customizing Paragraphs 3 More Paragraph Changes Highlight a paragraph in Word by applying borders and shading. Sort paragraphs to control.
Addison Wesley is an imprint of © 2010 Pearson Addison-Wesley. All rights reserved. Chapter 7 The Game Loop and Animation Starting Out with Games & Graphics.
Overview of Previous Lesson(s) Over View  Microsoft Foundation Classes (MFC)  A set of predefined classes upon which Windows programming with Visual.
Assign one variable to each group of radio buttons To do this, assign one integer variable to the first radio button in each group. All the subsequent.
Microsoft Access 2010 Chapter 8 Advanced Form Techniques.
Layers, Image Maps, and Navigation Bars
Object Oriented Programming Dr. Ennis-Cole CECS 5100.
Bitmap (Chapter 15).
Visual C++ Programming: Concepts and Projects Chapter 12B: Linked List (Tutorial)
Copyright © Curt Hill More Components Varying the input of Dev-C++ Windows Programs.
Visual Basic for Application - Microsoft Access 2003 Programming applications using Objects.
Chapter2: Drawing a Window
Chapter 8 Dialog Boxes and Property Sheet
Chapter 6: FILE I/O and Serialize CFile class. FILE I/O Serialization and the CArchive Class.
Chapter 7 Controls. List box control 3 List Box Control(1/8) Listbox control: –Display lists of text strings called items –Optionally sort the items.
1 Chapter 16 Creating the Document and Improving the View.
Part II Document/View Architecture. Chapter 9 Documents, Views, and the Single Document Interface.
Drawing in Windows. To help with drawing on the Windows operating system, Microsoft created the Graphical Device Interface, abbreviated as GDI. – It is.
Chapter 11 Enhancing an Online Form and Using Macros Microsoft Word 2013.
Chapter 16 (cont.) Drawing in a Window Using the Mouse
MULTIPLE DOCUMENTS AND MULTIPLE VIEWS Prosise - Chapter 11
Document/View Architecture
Chapter 2: The Visual Studio .NET Development Environment
Steps to Build Frame Window Recipe Application
Chapter 6 CS 3370 – C++ Functions.
Chapter 17 Creating the Document and Improving the View
Microsoft Access 2007 – Level 2
Friend Class Friend Class A friend class can access private and protected members of other class in which it is declared as friend. It is sometimes useful.
Motivation and Overview
Toolbars and Status Bars
Using Procedures and Exception Handling
This pointer, Dynamic memory allocation, Constructors and Destructor
Chapter 7 Advanced Form Techniques
Array Lists Chapter 6 Section 6.1 to 6.3
Variables and Arithmetic Operations
Exercise 28 - Skills Vector tools enable you to create perfectly formed shapes and lines of all sorts. What’s more the vector objects keep their shape.
Tutorial 19 - Microwave Oven Application Building Your Own Classes and Objects Outline Test-Driving the Microwave Oven Application Designing.
Chapter 5 The MFC Collection Classes
Benchmark Series Microsoft Word 2016 Level 1
DREAMWEAVER MX 2004 Chapter 3 Working with Tables
Items, Group Boxes, Check Boxes & Radio Buttons
DREAMWEAVER MX 2004 Chapter 7 Working with Layers
Chapter 4 Menu and Chapter 6 File I/O
Chapter 5 The MFC Collection Classes
Polymorphism Professor Hugh C. Lauer CS-2303, System Programming Concepts (Slides include materials from The C Programming Language, 2nd edition, by Kernighan.
Object-Oriented Programming: Inheritance and Polymorphism
9-10 Classes: A Deeper Look.
EECE.3220 Data Structures Instructor: Dr. Michael Geiger Spring 2019
Overview of the IDE Visual Studio .NET is Microsoft’s Integrated Development Environment (IDE) for creating, running and debugging programs (also.
Chapter 14 Drawing in a Window
9-10 Classes: A Deeper Look.
四時讀書樂 (春) ~ 翁森 山光照檻水繞廊,舞雩歸詠春風香。 好鳥枝頭亦朋友,落花水面皆文章。 蹉跎莫遣韶光老,人生唯有讀書好。
Chapter 16 Drawing in a Window
The List Container and Iterators
Presentation transcript:

Chapter 17 Creating the Document and Improving the View

The Sketcher Document Does Not Remember What You Have Drawn Whenever you resize the window, the elements disappear! Inspect class CSketcherDoc, you only have the following data members: protected: // Current element type ElementType m_Element; // Current drawing color COLORREF m_Color;

Store Elements in a List (P.1010) Data Member: std::list<CElement*> m_ElementList; Member Function: void AddElement(CElement* pEleemnt) { m_ElementList.push_back(pElement); } To Make CSketcherDoc recognize these data types: #include <list> #include "Elements.h"

Destroy the elements in the destructor CSketcherDoc::~CSketcherDoc() { // Delete the element pointed to by each list entry for (auto iter = m_ElementList.begin(); iter != m_ElementList.end(); ++iter) delete *iter; // Finally delete all pointers m_ElementList.clear(); } The auto keyword specifies the correct data type according to the initial value.

const_iterator The list is owned by the list, as a protected data member. You can’t access it directly from the view. class CSketcherDoc : public CDocument { // Operations public: // Add an element to the list void AddElement(CElement* pElement) { m_ElementList.push_back(pElement); } // Get list begin iterator std::list<CElement*>::const_iterator begin() const { return m_ElementList.begin(); } // Get list end iterator std::list<CElement*>::const_iterator end() const { return m_ElementList.end(); }

Not every element needs to be redrawn

Drawing only two elements improves the performance

Determine which element needs to be redrawn RectVisible() determines whether a rectangle area overlaps the area that Windows must redraw. void CSketcherView::OnDraw(CDC* pDC) { CSketcherDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; CElement* pElement(nullptr); for (auto iter = pDoc->begin(); iter != pDoc->end(); ++iter) pElement = *iter; if (pDC->RectVisible(pElement->GetBoundRect())) pElement->Draw(pDC); // If the element is visible // ... draw it }

Adding an Element to the Document OnLButtonUP(), add the temporary element to the document. void CSketcherView::OnLButtonUp(UINT nFlags, CPoint point) { if (this == GetCapture()) ReleaseCapture(); // Stop capturing mouse messages // Make sure there is an element if (m_pTempElement) // Call a document class function to store the element // pointed to by m_pTempElement in the document object GetDocument()->AddElement(m_pTempElement); InvalidateRect(nullptr); // Redraw the current window m_pTempElement = 0; // Reset the element pointer } Note that the statement deleting m_pTempElement has been removed. The document destructor will handle this.

Exercising the Document Now the document remembers all the elements you have drawn. Try to draw “The Happy Programmer”, and then resize the window.

Creating Multiple Views of a Document

Updating Multiple Views Right now, if you draw in a view, the other view will not be updated automatically. Each view is acting independently of the others. They don’t know what’s happening in other views. void CSketcherView::OnLButtonUp(UINT nFlags, CPoint point) { if (this == GetCapture()) ReleaseCapture(); // Stop capturing mouse messages // Make sure there is an element if (m_pTempElement) // Call a document class function to store the element // pointed to by m_pTempElement in the document object GetDocument()->AddElement(m_pTempElement); // Tell the views GetDocument()->UpdateAllViews(nullptr, 0, m_pTempElement); InvalidateRect(nullptr); // Redraw the current window m_pTempElement = 0; // Reset the element pointer }

Useful when the current view is already up to date UpdateAllViews() Useful when the current view is already up to date

Add an override for OnUpdate() Right-click CSketcherView and choose Override in the Properties Window. <Add> OnUpdate() void CSketcherView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { if (pHint) InvalidateRect( static_cast<CElement*>(pHint)->GetBoundRect()); else InvalidateRect(nullptr); } Now both views are updated.

Scrolling Views Change the base class for CSketcherView from CView to CScrollView. In SketcherView.h: class CSketcherView : public CScrollView In SketcherView.cpp: IMPLEMENT_DYNCREATE(CSketcherView, CScrollView) BEGIN_MESSAGE_MAP(CSketcherView, CScrollView)

SetScrollSizes()

Specify the size and scrolling distance override void CSketcherView::OnInitialUpdate() { CScrollView::OnInitialUpdate(); // Define document size CSize DocSize(20000, 20000); // Set mapping mode and document size SetScrollSizes(MM_TEXT, DocSize, CSize(500,500), CSize(50,50)); }

Exercise to Demo Use a vector instead of a list (as in Chapter 17) to store the elements.

Deleting and Moving Shapes Highlighting Elements Implementing a Context Menu Servicing the Menu Messages Deleting an Element Moving an Element

Context Menus Right-click will select an element and pops up a menu relating to actions that can be performed on that object. For different elements, different menus will be displayed. That’s why it is call a “context-sensitive menu”.

You Will Need Two Context Menus When there is an element under the mouse cursor: Move and Delete When there isn’t: Menu items from the Element and Color menus

Implementing a Context Menu Resource View Right-click the Menu folder Insert Menu The default ID is IDR_MENU1 Select this new menu, and pressing Alt-Enter to display the Properties window. Change its resource ID to be IDR_ELEMENT_MENU.

Create items on the menu Editor pane. The caption won’t be displayed to the user. Add the Move and Delete items to the element pop-up. The default IDs are ID_ELEMENT_MOVE and ID_ELEMENT_DELETE.

IDR_NOELEMENT_MENU Creating another menu with ID IDR_NOELEMENT_MENU The caption no element won’t be shown to users. Copy all items from the Element menu and the Color menu. Click the first item and then click the last item while holding down the Shift key. Press Ctrl+C to copy. Click the no element menu. Press Ctrl+V to paste. The copied menu items will have the same IDs as the originals. You may have a separator between the Element menu items and the Color menu items.

Associating a Menu with a Class AddMenu() function in an CContextManager object. void CSketcherApp::PreLoadState() { // Delete the remarked portion on P.1023 GetContextMenuManager()->AddMenu( _T("Element menu"), IDR_ELEMENT_MENU); _T("No element menu"), IDR_NOELEMENT_MENU); } The _T() macro selects the correct type for the string, depending on whether or not the _UNICODE symbol is defined.

Identifying a Selected Element An element is a sketch will be selected whenever the mouse cursor is within the bounding rectangle. Add FindElement() to the document class as a public member: // Finds the element under the point CElement* CSketcherDoc::FindElement(const CPoint& point) const { for (auto rIter = m_ElementList.rbegin(); rIter != m_ElementList.rend(); ++rIter) if ((*rIter)->GetBoundRect().PtInRect(point)) return *rIter; return nullptr; }

Check which element is selected whenever the mouse moves Use a variable m_pSelected to store the address of the element under the mouse cursor, or nullptr if there isn’t one. void CSketcherView::OnMouseMove(UINT nFlags, CPoint point) { // Define a Device Context object for the view CClientDC aDC(this); // DC is for this view if((nFlags & MK_LBUTTON) && (this == GetCapture()) ) { // Code as before ... } else { // We are not creating an element, so select an element CSketcherDoc* pDoc=GetDocument(); m_pSelected = pDoc->FindElement(point);

m_pSelected Add m_pSelected as a protected member of the CSketcherView class as type CElement*. Initialize this member to nullptr in the view class constructor.

ShowPopupMenu() Look at CSketcherView class implementation. In OnRButtonUP() handler, it already calls the OnContextMenu() handler to show a popup menu. Modify OnContextMenu(): void CSketcherView::OnContextMenu(CWnd* pWnd, CPoint point) { #ifndef SHARED_HANDLERS // theApp.GetContextMenuManager()->ShowPopupMenu( // IDR_POPUP_EDIT, point.x, point.y, this, TRUE); if (m_pSelected) theApp.GetContextMenuManager()->ShowPopupMenu( IDR_ELEMENT_MENU, point.x, point.y, this); else IDR_NOELEMENT_MENU, point.x, point.y, this); #endif }

Try It Out Build and execute Sketcher. Right-click the mouse, or press Shift+F10 A context menu will be displayed. If there are no elements under the cursor, the second context pop-up appears, enabling you to change the element type and color. If there is an element under the cursor, the first context menu will appear with Move and Delete on it. It won’t do anything at this moment.

Highlighting Elements You should draw the element under the cursor with a different color, so that users can make sure the right-click will be applied on which element. Change the Draw() member function for an element. Pass an extra argument m_pSelected, which is the currently-selected element Compare it with this pointer, and draw in a special color if this == m_pSelected.

CSketcherView::OnDraw() void CSketcherView::OnDraw(CDC* pDC) { CSketcherDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; CElement* pElement(nullptr); for (auto iter = pDoc->begin(); iter != pDoc->end(); ++iter) pElement = *iter; // If the element is visible if (pDC->RectVisible(pElement->GetBoundRect())) pElement->Draw(pDC, m_pSelected); // ... draw it }

Draw() in CElement class Modify the definition of Draw() in the base class CElement class CElement : public CObject { protected: int m_PenWidth; // Pen width COLORREF m_Color; // Color of an element CElement(); public: virtual ~CElement(); // Virtual draw operation virtual void Draw(CDC* pDC, CElement* pElement=nullptr) {} // Get the bounding rectangle for an element CRect GetBoundRect(void); }; Remember to remove the virtual CElement::Draw() in Elements.cpp

Change the CLine class definition class CLine : public CElement { public: virtual ~CLine(void); // Function to display a line virtual void Draw(CDC* pDC, CElement* pElement=nullptr); // Constructor for a line object CLine(const CPoint& start, const CPoint& end, COLORREF aColor); protected: CPoint m_StartPoint; // Start point of line CPoint m_EndPoint; // End point of line CLine(void); // Default constructor should not be used };

Implementation of CLine::Draw() void CLine::Draw(CDC* pDC, CElement* pElement) { // Create a pen for this object and // initialize it to the object color and line width of 1 pixel CPen aPen; if(!aPen.CreatePen(PS_SOLID, m_PenWidth, this==pElement ? SELECT_COLOR : m_Color)) // Pen creation failed. Abort the program AfxMessageBox(_T("Pen creation failed drawing a line"), MB_OK); AfxAbort(); } CPen* pOldPen = pDC->SelectObject(&aPen); // Select the pen // Now draw the line pDC->MoveTo(m_StartPoint); pDC->LineTo(m_EndPoint); pDC->SelectObject(pOldPen); // Restore the old pen In SketcherConstants.h: const COLORREF SELECT_COLOR = RGB(255,0,180); Apply the same change on CRectangle, CCircle, and CCurve.

Tell MFC which elements to re-draw void CSketcherView::OnMouseMove(UINT nFlags, CPoint point) { // Define a Device Context object for the view CClientDC aDC(this); // DC is for this view if((nFlags & MK_LBUTTON) && (this == GetCapture()) ) { // Code as before } else { // We are not creating an element, so select an element CSketcherDoc* pDoc=GetDocument(); CElement* pOldSelected(m_pSelected); m_pSelected = pDoc->FindElement(point); if (m_pSelected != pOldSelected) { if (m_pSelected) InvalidateRect(m_pSelected->GetBoundRect(), FALSE); if (pOldSelected) InvalidateRect(pOldSelected->GetBoundRect(), FALSE); pDoc->UpdateAllViews(nullptr); If both pOldSelected and m_pSelected contain a valid address, the element has been already highlighted. If they are both zero, nothing is highlighted. So, you need to do something only when m_pSelected is not equal to pOldSelected. Not to erase the background Now try it out. The highlighted element is drawn in magenta.

Deleting an Element void CSketcherView::OnElementDelete() { if (m_pSelected) CSketcherDoc* pDoc = GetDocument(); // Get the document ptr pDoc->DeleteElement(m_pSelected); // Delete the element pDoc->UpdateAllViews(nullptr); // Redraw all the views m_pSelected = nullptr; // Reset selected element ptr }

DeleteElement() Added as a public member of CSketcherDoc (P.1031) void CSketcherDoc::DeleteElement(CElement* pElement) { if (pElement) // Remove the pointer from the list m_ElementList.remove(pElement); // Delete the element from the heap delete pElement; } List Heap CElement