UCanCode
Software focuses on general application software development. We provide complete solution for developers. No matter you want to develop a simple database
workflow application, or an large flow/diagram based system, our product will provide a complete solution for you. Our product had been used by hundreds of top companies around the world!
"100% source code provided! Free you from not daring to use components because of unable to master the key technology of components!"
|
GDI
Topics: Using a Trajectory
|
|
A
trajectory is a path along which an object
travels. In one example, an object could go from
one point to another without coming back. In
another example, an object could go back and forth
from one object to another. The study or
implementation of trajectories is common in
graphics applications, in games, or other
simulation types.
Practical Learning: Introducing Trajectories
|
|
|
- To
start this exercise, create an MFC Application
named Trajectory1
- Create
it as a Single Document type
- To
fill the window's content with a black
background, access the source file of the view
and change its OnDraw event as follows:
void CTrajectory1View::OnDraw(CDC* pDC)
{
CTrajectory1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
CBrush brsBlack;
CRect rctClient;
brsBlack.CreateSolidBrush(RGB(0, 0, 0));
GetWindowRect(&rctClient);
CBrush *pOldBrush = pDC->SelectObject(&brsBlack);
pDC->Rectangle(0, 0, rctClient.Width(), rctClient.Height());
pDC->SelectObject(pOldBrush);
}
|
- Execute
the application to see the result
The
primary implementation of using a trajectory
consist of moving an object or a shape along a
path. To do this, you can draw the shape in
response to a timer.
Practical Learning: Moving a Shape
|
|
- Using
the Resource Symbols dialog box, create an ID
named IDT_MOVE
- Generate
the OnInitialUpdate event for the view class
and use it to initialize the timer as follows:
void CTrajectory1View::OnInitialUpdate()
{
CView::OnInitialUpdate();
SetTimer(IDT_MOVE, 10, NULL);
// TODO: Add your specialized code here and/or call the base class
}
|
- In
the view header file, declare the following
variables:
// Trajectory1View.h : interface of the CTrajectory1View class
//
#pragma once
class CTrajectory1View : public CView
{
protected: // create from serialization only
CTrajectory1View();
DECLARE_DYNCREATE(CTrajectory1View)
// Attributes
public:
CTrajectory1Doc* GetDocument() const;
// Operations
public:
static const int ShapeWidth = 45;
static const int ShapeHeight = 15;
int x;
int y;
bool MovingRight;
// Overrides
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// Implementation
public:
virtual ~CTrajectory1View();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in Trajectory1View.cpp
inline CTrajectory1Doc* CTrajectory1View::GetDocument() const
{ return reinterpret_cast<CTrajectory1Doc*>(m_pDocument); }
#endif
|
- In
the constructor of the view class, initialize
the variables as follows:
CTrajectory1View::CTrajectory1View()
{
// TODO: add construction code here
x = 0;
y = 200;
MovingRight = false;
}
|
- Change
the OnDraw event as follows:
void CTrajectory1View::OnDraw(CDC* pDC)
{
CTrajectory1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
CPen penYellow;
CBrush brsBlack, brsFuchsia;
CRect rctClient;
brsBlack.CreateSolidBrush(RGB(0, 0, 0));
brsFuchsia.CreateSolidBrush(RGB(255, 0, 255));
penYellow.CreatePen(PS_SOLID, 1, RGB(255, 255, 0));
GetWindowRect(&rctClient);
CBrush *pOldBrush = pDC->SelectObject(&brsBlack);
pDC->Rectangle(0, 0, rctClient.Width(), rctClient.Height());
pOldBrush = pDC->SelectObject(&brsFuchsia);
CPen *pOldPen = pDC->SelectObject(&penYellow);
pDC->RoundRect(this->x, this->y, this->x + ShapeWidth,
this->y + ShapeHeight, 5, 5);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
|
- Generate
the event of the WM_TIMER
message for the view class and implement it as
follows:
void CTrajectory1View::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CRect rctClient;
GetWindowRect(&rctClient);
if( this->x < 0 )
{
this->x = 0;
this->MovingRight = true;
}
if( this->x > rctClient.Width() - ShapeWidth )
{
this->x = rctClient.Width() - ShapeWidth;
this->MovingRight = FALSE;
}
if( x < 0 )
{
x = 0;
MovingRight = TRUE;
}
if( x > rctClient.Width() - ShapeWidth )
{
x = rctClient.Width() - ShapeWidth;
MovingRight = FALSE;
}
Invalidate();
if( MovingRight == TRUE )
x++;
else
x--;
CView::OnTimer(nIDEvent);
}
|
- Generate
the event of the WM_ERASEBKGND
message of the view class and change its
return value as follows:
BOOL CTrajectory1View::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE; // CView::OnEraseBkgnd(pDC);
}
|
- Execute
the application to see the result:
- Close
it and return to MSVC
Object
oriented programming consists of creating objects
that each can perform a specific tucancode.net and take of
assignments related to it. In trajectory-related
programming, you can create a class for each
object or shape. This can make it easy to
recognize and use the object. If you happen to use
different objects, you can then customize the
behavior of each.
Practical Learning: Creating a Shape Class
|
|
- To create a
new class, on the main menu, click Project
-> Add Class...
- In the
Templates list, click C++ Class and click Add
- Set the Class
Name to CShape and press Enter
- Change the
header file as follows:
#pragma once
class CShape
{
public:
CShape(void);
public:
~CShape(void);
static const int Width = 45;
static const int Height = 15;
int x;
int y;
bool MovingRight;
void Draw(CDC* pDC);
void Move(CRect rctClient);
};
|
- Change the
source file as follows:
#include "StdAfx.h"
#include "Shape.h"
CShape::CShape(void)
: x(0),
y(150),
MovingRight(false)
{
}
CShape::~CShape(void)
{
}
void CShape::Draw(CDC* pDC)
{
CPen penYellow;
CBrush brsFuchsia;
brsFuchsia.CreateSolidBrush(RGB(255, 0, 255));
penYellow.CreatePen(PS_SOLID, 1, RGB(255, 255, 0));
CBrush *pOldBrush = pDC->SelectObject(&brsFuchsia);
CPen *pOldPen = pDC->SelectObject(&penYellow);
pDC->RoundRect(this->x,
this->y,
this->x + CShape::Width,
this->y + CShape::Height,
5,
5);
pDC->SelectObject(pOldBrush);
}
void CShape::Move(CRect rctClient)
{
if( this->x < 0 )
{
this->x = 0;
this->MovingRight = true;
}
if( this->x > rctClient.Width() - CShape::Width )
{
this->x = rctClient.Width() - CShape::Width;
this->MovingRight = FALSE;
}
}
|
- Access the
header file of the view class and change it as
follows:
// Trajectory2View.h : interface of the CTrajectory1View class
//
#pragma once
#include "Shape.h"
class CTrajectory1View : public CView
{
protected: // create from serialization only
CTrajectory1View();
DECLARE_DYNCREATE(CTrajectory1View)
// Attributes
public:
CTrajectory1Doc* GetDocument() const;
// Operations
public:
CShape *shape;
// Overrides
public:
. . .
};
#ifndef _DEBUG // debug version in Trajectory2View.cpp
inline CTrajectory1Doc* CTrajectory1View::GetDocument() const
{ return reinterpret_cast<CTrajectory1Doc*>(m_pDocument); }
#endif
|
- Access the
source file of the view class and change it as
follows:
// Trajectory2View.cpp : implementation of the CTrajectory1View class
//
#include "stdafx.h"
#include "Trajectory2.h"
#include "Trajectory2Doc.h"
#include "Trajectory2View.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CTrajectory1View
IMPLEMENT_DYNCREATE(CTrajectory1View, CView)
BEGIN_MESSAGE_MAP(CTrajectory1View, CView)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_WM_TIMER()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
// CTrajectory1View construction/destruction
CTrajectory1View::CTrajectory1View()
{
// TODO: add construction code here
shape = new CShape;
}
CTrajectory1View::~CTrajectory1View()
{
delete shape;
}
BOOL CTrajectory1View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
// CTrajectory1View drawing
void CTrajectory1View::OnDraw(CDC* pDC)
{
CTrajectory1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
CPen penYellow;
CBrush brsBlack, brsFuchsia;
CRect rctClient;
brsBlack.CreateSolidBrush(RGB(0, 0, 0));
brsFuchsia.CreateSolidBrush(RGB(255, 0, 255));
penYellow.CreatePen(PS_SOLID, 1, RGB(255, 255, 0));
GetWindowRect(&rctClient);
CBrush *pOldBrush = pDC->SelectObject(&brsBlack);
pDC->Rectangle(0, 0, rctClient.Width(), rctClient.Height());
shape->Draw(pDC);
pDC->SelectObject(pOldBrush);
}
. . .
// CTrajectory1View message handlers
void CTrajectory1View::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CRect rctClient;
GetWindowRect(&rctClient);
shape->Move(rctClient);
Invalidate();
if( shape->MovingRight == TRUE )
shape->x++;
else
shape->x--;
CView::OnTimer(nIDEvent);
}
void CTrajectory1View::OnInitialUpdate()
{
CView::OnInitialUpdate();
SetTimer(IDT_MOVE, 10, NULL);
// TODO: Add your specialized code here and/or call the base class
}
BOOL CTrajectory1View::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE; // CView::OnEraseBkgnd(pDC);
}
|
- Execute the
application and notice that it produces the
same result
|
|
|
|