CS390-CPP

Lab 1: Programming a Graphic Editor in C++ in Windows

NOTE:

Here is a Java graphics editor in graph-editor-java.tar.Z. Download it in data.cs.purdue.edu and type "uncompress graph-editor-java.tar.Z; tar -xvf graph-editor-java.tar; javac BoilerDrawMain; java BoilerDrawMain". Read the sources and take ideas of how to implement the features in C++. I think this editor has better model than the one original Visual Studio sources.

This is approximately the grading form that will be used to grade your project.

The project will be graded with a demo sometime Thursday Feb 10th or Friday Feb 11th.

Introduction

In this lab you will write a graphical editor using the concepts of object oriented programming and C++. You will use MFC (Microsoft Foundation Classes) and Visual Studio.

Step 1. Get Visual Studio C++

To get Visual studio C++, go to the web site http://www.cs.purdue.edu/msdn and login with your carreer account. Go to "Software" and select Visual Studio 2008. Then download it and install it in your computer. Purdue students can download this software without any cost.

Step 2. Download the Initial Files

Download the initial file MyDraw.zip ( MyDraw) into your computer and unzip it. Then double click in the MyDraw Visual Studio solution. This will open Visual Studio. Now select the menu Build->Build Solution.
welcome

Once the application is built, select the menu Debug->Start Debugging. this will run the initial application. In the application select Figure->Line to put the editor in NewLine mode. The press the mouse and drag it to the opposite side of the line and release the mouse. To create another line select the menu Figure->Line again and repeat the same mouse sequence. To modify a line, click on the line and drag the control points. Also, you can select a line and move it. You can select multiple lines by pressing the mouse in a upper left corner and dragging the mouse to a lower right corner to create a selection rectangle. Once multiple lines are selected, you can move all the lines by  moving only one of the lines.

lines

Step 3. Code Organization

The code is organized as follows.

Code generated by the New Project Wizard for MFC Applications:
Code that implements the initial graphic editor. You will need to add more classes for more functionality.
The MyDraw application initially creates one MyDrawDoc and a MyDrawView. The MyDrawDoc has as a member variable a Drawing object that represents the drawing shown on the screen. The MyDrawView has a pointer to the document it represents. Also MyDrawView has a OnDraw() method that is called when the window has to be drawn. This OnDraw method gets the document and from there it gets the Drawing object and calls the method pDoc->drawing.draw(pDC); to draw all the figures in the drawing. Also the MyDrawView defines mouse event call backs such as OnMouseMove() that call the method pDoc->drawing.OnMouse(this, nFlags, point); in the Drawing class.

In this project you will mostly add functionality to the Drawing class as well as add new classes for the different objects. You will also need to learn how to generate event handlers for the different events using Visual Studio.

At this point see each of the files mentioned above so you can get familiar with the code. You do not need to understand the files generated with the Wizard in the first list, but you should understand the other files in the second list that make the graphic editor.

Step 5. Creating a Rectangle Class

In this step you will build a MyRectangle class so you can get familiar with Visual Studio and the files that make the Graphic Editor.

1. In the Solution Explorer in the left side, right click on top of the "Header Files" folder and select Add->Class

Add Class

In Categories: select C++ and in templates select C++ Class and Add.
add class 2

Then in the next window type as Class name "MyRectangle" and as base class "Figure". This is going to add two new files MyRectangle.h and MyRectangle.cpp to the project. Select "Finish".

classname

You can use the implementation of Line.h and Line.cpp to came up with the implementation of MyRectangle.h and MyRectangle.cpp

Now in MyRectangle.h add the following:

#pragma once
#include "Figure.h"

class MyRectangle :
    public Figure
{
public:
    MyRectangle(int x0, int y0, int x1, int y1);
    ~MyRectangle(void);

    // Draw a rectangle using graphic context pDC
    void draw(CDC* pDC);

    // Return true if rectangle is close to coordinates (x,y)
    bool isCloseTo(int x, int y);
};

and in Rectangle.cpp add the folowing:

#include "StdAfx.h"
#include "MyRectangle.h"

MyRectangle::MyRectangle(int x0, int y0, int x1, int y1)
:Figure(Figure::FigureType::Rectangle)
{
    controlPoints.push_back(new ControlPoint(this, x0,y0));
    controlPoints.push_back(new ControlPoint(this, x1,y1));
}

MyRectangle::~MyRectangle(void)
{
}

// Draw a rectangle using graphic context pDC
void MyRectangle::draw(CDC* pDC)
{
    ControlPoint * p0 = controlPoints.at(0);
    ControlPoint * p1 = controlPoints.at(1);
   
    // Find minx, miny, maxx, maxy
    int minX = (p0->getX()<p1->getX())?p0->getX():p1->getX();
    int minY = (p0->getY()<p1->getY())?p0->getY():p1->getY();
    int maxX = (p0->getX()<p1->getX())?p1->getX():p0->getX();
    int maxY = (p0->getY()<p1->getY())?p1->getY():p0->getY();

    // Draw rectangle
    CPen pen( PS_SOLID, 0, RGB( 0, 0, 0 ) );
    CPen* pOldPen = pDC->SelectObject( &pen );
    pDC->MoveTo(minX, minY);
    pDC->LineTo(maxX, minY);
    pDC->LineTo(maxX, maxY);
    pDC->LineTo(minX, maxY);
    pDC->LineTo(minX, minY);
}

// Return true if rectangle is close to coordinates (x,y)
bool MyRectangle::isCloseTo(int x, int y)
{
    ControlPoint * p0 = controlPoints.at(0);
    ControlPoint * p1 = controlPoints.at(1);
   
    // Find minx, miny, maxx, maxy
    int minX = (p0->getX()<p1->getX())?p0->getX():p1->getX();
    int minY = (p0->getY()<p1->getY())?p0->getY():p1->getY();
    int maxX = (p0->getX()<p1->getX())?p1->getX():p0->getX();
    int maxY = (p0->getY()<p1->getY())?p1->getY():p0->getY();

    // Check if (x,y) is close to any of the borders.
    if (Figure::distancePointToLine(x, y, minX, minY, maxX, minY) < Figure::smallDistance ||
        Figure::distancePointToLine(x, y, maxX, minY, maxX, maxY) < Figure::smallDistance ||
        Figure::distancePointToLine(x, y, minX, maxY, maxX, maxY) < Figure::smallDistance ||
        Figure::distancePointToLine(x, y, minX, minY, minX, maxY) < Figure::smallDistance) {
        return true;
    }

    return false;
}


Now we are going to add a new item in the Figure menu. In the left side of Visual Studio select the "Resource View" and double click in IDR_MyDrawTYPE. Then select the Figure->Rectangle and right click on it to select "Add Event Handler".

recthandler

In "Message Type" select "COMMAND" and in "Class List:" select "CMyDrawView". The press "Add and Edit". This will generate the code for the event handler Figure->Rectangle

addhandler2

Now in the file CMyDrawView find the method CMyDrawView::OnFigureRectangle() and add the following code.

void CMyDrawView::OnFigureRectangle()
{
    CMyDrawDoc* pDoc = GetDocument();
    pDoc->drawing.setEditMode(Drawing::NewRectangleMode);
}

This will set the Drawing editor into NewRectangleMode.

In the file Drawing.h find enum EditMode and add the new mode NewRectangleMode:

        // Mode of the Drawing editor.
    enum EditMode {SelectMode, NewLineMode, NewRectangleMode };

In the file Drawing.cpp at the top add:

#include "MyRectangle.h"

and in the method void Drawing::OnMouse(CView * cview, int nFlags, CPoint point) find the line

            if (this->editMode == Drawing::NewLineMode ) {
              ...
            }

and immediately after add the section for the rectangle. This code is very simmilar to the section for the New Line.

            else if (this->editMode == Drawing::NewRectangleMode ) {

                // Edit mode is NewRectangleMode.
                // This is because the user just selected the Figure->Rectangle menu

                // Create a new rectangle.
                MyRectangle * rectangle = new MyRectangle(point.x, point.y, point.x, point.y);

                // Add to the list of figures
                this->figures.push_back(rectangle);

                // Now switch to select mode
                this->editMode = SelectMode;

                // Select only the last control point of the line
                // so dragging will modify this control point.
                this->selectAll(false);
                rectangle->selectLast(true);

                // Update previous mouse coordinates
                this->previousX = point.x;
                this->previousY = point.y;

                // Redraw window. This will call the draw method.
                cview->RedrawWindow();
            }

            else if (this->editMode == Drawing::SelectMode) {

Now you should be able to Build->Build Solution and run Debug->start Debugging

selectrect
rects2

Here is a tutorial about programming C++ applications in Visual Studio with the MFC. Also you can google for "Visual Studio C++ MFC tutorial" for more resources.

Step 6. First Part of the project

We will divide this project in two parts. In the frst part you will implement:

1. Ovals. Add a circle class.
2. Delete Figure
3. Add a new menu to change the color used to draw the figures. Add a new variable currentColor to the Drawing class and use this color when drawing the figures. You can either add a new Color Menu with the multiple color or use the MFC color dialog (google for it).
4. Also implement Groups. You can select a group of figures and group them into a single figure. Yu can add the oprations Group, Ungroup, Bring Top, Push Back to change the ordering of the figures.

Step 7. Second Part of the project

In this second part of the project you will add:

1. Copy/Paste
2. Add a Save/Open to save and open the drawing in disk.
3. Add a text figure. When choosing Figure->text, a dialog will show so the user can type the text to show and it will display it.

The project will be graded Friday February 20th. We will post the demo times before that day so you may sign up.
To turnin your project zip the directory MyDraw/ and transfer it to lore. Then type
turnin -c cs390lang -p lab1 MyDraw.zip

Additional:


The project will be graded by demostrating the project to the TA. We will post the demo times later.