yeah,大体结构完成了。就剩下具体的添加各种处理类和完善Shape类体系各成员的功能了。贴出来看看:
shapeclass.cpp 代码: #include "shapeclass.h"
//---------------- SRect Methods------------------------//
void SRect::DrawSelf(HDC hdc) const
{
Rectangle(hdc, ptLT.x, ptLT.y, ptRB.x, ptRB.y);
}
void SRect::Move(POINT ptDirect)
{
ptLT.x += ptDirect.x;
ptLT.y += ptDirect.y;
ptRB.x += ptDirect.x;
ptRB.y += ptDirect.y;
}
void SRect::Rotate(POINT ptCenter, double dArg)
{
}
void SRect::SetRect(POINT _ptLT, POINT _ptRB)
{
ptLT.x = _ptLT.x;
ptLT.y = _ptLT.y;
ptRB.x = _ptRB.x;
ptRB.y = _ptRB.y;
}
void SRect::GetRect(POINT& _ptLT, POINT& _ptRB) const
{
_ptLT.x = ptLT.x;
_ptLT.y = ptLT.y;
_ptRB.x = ptRB.x;
_ptRB.y = ptRB.y;
}
//---------------------------SEllipse Method--------------------------------//
void SEllipse::DrawSelf(HDC hdc) const
{
Ellipse(hdc, ptLT.x, ptLT.y, ptRB.x, ptRB.y);
}
void SEllipse::Move(POINT ptDirect)
{
ptLT.x += ptDirect.x;
ptLT.y += ptDirect.y;
ptRB.x += ptDirect.x;
ptRB.y += ptDirect.y;
}
void SEllipse::Rotate(POINT ptCenter, double dArg)
{
}
void SEllipse::SetEllipse(POINT _ptLT, POINT _ptRB)
{
ptLT.x = _ptLT.x;
ptLT.y = _ptLT.y;
ptRB.x = _ptRB.x;
ptRB.y = _ptRB.y;
}
void SEllipse::GetEllipse(POINT& _ptLT, POINT& _ptRB) const
{
_ptLT.x = ptLT.x;
_ptLT.y = ptLT.y;
_ptRB.x = ptRB.x;
_ptRB.y = ptRB.y;
}
//--------------------------SPolygon Method---------------------------//
void SPolygon::DrawSelf(HDC hdc) const
{
POINT * pt = new POINT[vecVertex.size()];
for (int i = 0; i < vecVertex.size(); ++i)
pt[i] = vecVertex[i];
Polygon(hdc, pt, vecVertex.size());
}
void SPolygon::Move(POINT ptDirect)
{
for (int i = 0; i < vecVertex.size(); ++i)
{
vecVertex[i].x += ptDirect.x;
vecVertex[i].y += ptDirect.y;
}
}
void SPolygon::Rotate(POINT ptCenter, double dArg)
{
}
void SPolygon::SetPolygon(std::vector<POINT> const& vecIn)
{
vecVertex = vecIn;
}
void SPolygon::GetPolygon(std::vector<POINT>& vecOut) const
{
vecOut = vecVertex;
} shapeclass.h 代码: #include <windows.h>
#include <vector>
#ifndef __SHAPECLASS_H__
#define __SHAPECLASS_H__
class Shape
{
public:
virtual ~Shape(){}
virtual void DrawSelf(HDC hdc) const = 0;
virtual void Move(POINT ptDirect) = 0;
virtual void Rotate(POINT ptCenter, double dArg) = 0;
private:
//static std::list<Shape*>
};
class SRect : public Shape
{
public:
SRect(POINT _ptLT, POINT _ptRB) : ptLT(_ptLT), ptRB(_ptRB) {}
virtual ~SRect() {}
virtual void DrawSelf(HDC hdc) const;
virtual void Move(POINT ptDirect);
virtual void Rotate(POINT ptCenter, double dArg);
void SetRect(POINT _ptLT, POINT _ptRB);
void GetRect(POINT& _ptLT, POINT& _ptRB) const;
private:
POINT ptLT; //lefttop point
POINT ptRB; //rightbottom point
};
class SEllipse : public Shape
{
public:
SEllipse(POINT _ptLT, POINT _ptRB) : ptLT(_ptLT), ptRB(_ptRB) {}
virtual ~SEllipse() {}
virtual void DrawSelf(HDC hdc) const;
virtual void Move(POINT ptDirect);
virtual void Rotate(POINT ptCenter, double dArg);
void SetEllipse(POINT _ptLT, POINT _ptRB);
void GetEllipse(POINT& _ptLT, POINT& _ptRB) const;
private:
POINT ptLT; //lefttop point
POINT ptRB; //rightbottom point
};
class SPolygon : public Shape
{
public:
SPolygon(std::vector<POINT> const vecVtx) : vecVertex(vecVtx) {}
virtual ~SPolygon() {}
virtual void DrawSelf(HDC hdc) const;
virtual void Move(POINT ptDirect);
virtual void Rotate(POINT ptCenter, double dArg);
void SetPolygon(std::vector<POINT> const& vecIn);
void GetPolygon(std::vector<POINT>& vecOut) const;
private:
std::vector<POINT> vecVertex;
};
#endif shapemap.h 代码: #include <windows.h>
#include "shapeclass.h"
#include "mousecapture.h"
#include <algorithm>
#ifndef __SHAPERMAP_H__
#define __SHAPERMAP_H__
class ShapeMap;
//-----------------manage all the shapes--------------------//
class ShapeManager
{
public:
ShapeManager() : cur_handle(NULL) {}
~ShapeManager();
void MappingHandle(int x, int y);
bool ExistHandle() { return cur_handle == NULL ? false : true; }
void Add(ShapeMap *);
void PostMouseMsg(HWND, UINT, WPARAM, LPARAM);
void Draw(HDC) const;
private:
std::vector<ShapeMap*> vecShapes;
ShapeCapture * cur_handle;
};
//------------------manage message for creating------------------//
class FactoryManager
{
public:
FactoryManager() : cur_handle(NULL) {}
~FactoryManager();
void SetHandle(FactoryCapture * new_handle);
bool ExistHandle() const { return cur_handle == NULL ? false : true; }
void PostMouseMsg(HWND, UINT, WPARAM, LPARAM);
void Draw(HDC hdc) const;
private:
FactoryCapture * cur_handle;
};
class ShapeMap
{
public:
virtual ~ShapeMap() {}
virtual void Draw(HDC) const = 0;
virtual ShapeCapture * MappingHandle(int x, int y) = 0;
};
class SRectMap : public ShapeMap
{
public:
SRectMap(SRect const& src) : rc(src) {}
virtual ~SRectMap() {}
virtual void Draw(HDC) const;
virtual ShapeCapture * MappingHandle(int x, int y);
private:
SRect rc;
};
class SElliMap : public ShapeMap
{
public:
SElliMap(SEllipse const& selli) : el(selli) {}
virtual ~SElliMap() {}
virtual void Draw(HDC) const;
virtual ShapeCapture * MappingHandle(int x, int y);
private:
SEllipse el;
};
class SPolyMap : public ShapeMap
{
public:
SPolyMap(SPolygon const& spoly) : pl(spoly) {}
virtual ~SPolyMap() {}
virtual void Draw(HDC) const;
virtual ShapeCapture * MappingHandle(int x, int y);
private:
SPolygon pl;
};
#endif shapemap.cpp 代码: #include "shapermap.h"
#include <cmath>
//----------------------SRectMap methods------------------------//
ShapeCapture * SRectMap::MappingHandle(int x, int y)
{
POINT ptLT, ptRB;
rc.GetRect(ptLT, ptRB);
int xMin = std::min(ptLT.x, ptRB.x),
xMax = std::max(ptLT.x, ptRB.x),
yMin = std::min(ptLT.y, ptRB.y),
yMax = std::max(ptLT.y, ptRB.y);
if ((x > xMin && x < xMax) && (y > yMin && y < yMax))
return new MoveCapture(&rc);
return NULL;
}
void SRectMap::Draw(HDC hdc) const
{
rc.DrawSelf(hdc);
}
//----------------------SElliMap methods-----------------------//
ShapeCapture * SElliMap::MappingHandle(int x, int y)
{
POINT ptLT, ptRB;
el.GetEllipse(ptLT, ptRB);
int a = abs(ptLT.x - ptRB.x) / 2,
b = abs(ptLT.y - ptRB.y) / 2,
x0 = (ptLT.x + ptRB.x) / 2,
y0 = (ptLT.y + ptRB.y) / 2;
if (std::pow((double)(b * (x - x0)), 2) + std::pow((double)(a * (y - y0)), 2)
< std::pow((double)(a * b), 2))
return new MoveCapture(&el);
return NULL;
}
void SElliMap::Draw(HDC hdc) const
{
el.DrawSelf(hdc);
}
//--------------------------SPolyMap methods------------------------//
ShapeCapture * SPolyMap::MappingHandle(int x, int y)
{
return NULL;
}
void SPolyMap::Draw(HDC hdc) const
{
pl.DrawSelf(hdc);
}
//----------------------ShapeManager methods-------------------------//
ShapeManager::~ShapeManager()
{
delete cur_handle;
for (std::vector<ShapeMap *>::iterator it = vecShapes.begin();
it != vecShapes.end(); ++it)
delete (*it);
}
void ShapeManager::MappingHandle(int x, int y) //insert correct handle
{
if (ExistHandle())
return;
ShapeCapture * pmc;
for (std::vector<ShapeMap *>::reverse_iterator it = vecShapes.rbegin();
it != vecShapes.rend(); ++it)
{
if ((pmc = (*it)->MappingHandle(x, y)) != NULL)
{
cur_handle = pmc;
break;
}
}
}
void ShapeManager::Add(ShapeMap * psm)
{
vecShapes.push_back(psm);
}
void ShapeManager::PostMouseMsg(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (cur_handle == NULL) //if a handle exists then return
return;
//delete the existing handle when the process is finished
if (!cur_handle->PostMouseMsg(hwnd, message, wParam, lParam))
{
delete cur_handle;
cur_handle = NULL;
}
}
void ShapeManager::Draw(HDC hdc) const
{
for (std::vector<ShapeMap*>::const_iterator it = vecShapes.begin();
it != vecShapes.end(); ++it)
(*it)->Draw(hdc);
}
//-----------------------------FactoryManager methods-------------------------//
FactoryManager::~FactoryManager()
{
delete cur_handle;
}
void FactoryManager::SetHandle(FactoryCapture * new_handle)
{
if (cur_handle != NULL)
return;
cur_handle = new_handle;
}
void FactoryManager::PostMouseMsg(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (cur_handle == NULL)//if a handle exists then return
return;
//delete the existing handle when the process is finished
if (!cur_handle->PostMouseMsg(hwnd, message, wParam, lParam))
{
delete cur_handle;
cur_handle = NULL;
}
}
void FactoryManager::Draw(HDC hdc) const
{
if (cur_handle == NULL)
return;
cur_handle->Draw(hdc);
} mousecapture.h 代码: #include <windows.h>
#include <vector>
#include "shapeclass.h"
#ifndef __MOUSECAPTURE_H__
#define __MOUSECAPTURE_H__
//----------------------------Mouse message handles------------------//
class MouseCapture
{
public:
virtual ~MouseCapture() {}
virtual bool PostMouseMsg(HWND hwnd, UINT msgMouse, WPARAM wParam, LPARAM lParam) = 0;
};
class ShapeCapture : public MouseCapture
{
public:
virtual ~ShapeCapture() {}
virtual bool PostMouseMsg(HWND hwnd, UINT msgMouse, WPARAM wParam, LPARAM lParam) = 0;
};
class MoveCapture : public ShapeCapture //moving handle
{
public:
MoveCapture(Shape * pS) : pShape(pS) , cur_state(END) {}
virtual ~MoveCapture() {}
virtual bool PostMouseMsg(HWND, UINT, WPARAM, LPARAM);
private:
enum MOVE_STATE { MOVING, END } cur_state;
POINT ptStart;
Shape * pShape;
};
//------------------------Factory captures---------------------------//
class FactoryCapture : public MouseCapture
{
public:
virtual ~FactoryCapture() {}
virtual bool PostMouseMsg(HWND hwnd, UINT msgMouse, WPARAM wParam, LPARAM lParam) = 0;
virtual void Draw(HDC) const = 0;
};
class SRectFacCapture : public FactoryCapture //gather info for creating SRect
{
public:
SRectFacCapture() : cur_state(RB_INPUTED) {}
virtual ~SRectFacCapture() {};
virtual bool PostMouseMsg(HWND hwnd, UINT msgMouse, WPARAM wParam, LPARAM lParam);
virtual void Draw(HDC) const;
private:
enum CREATE_STATE { LT_INPUTED, RB_INPUTED } cur_state;
POINT ptLT, ptRB;
};
class SElliFacCapture : public FactoryCapture //gather info for creating SEllipse
{
public:
SElliFacCapture() : cur_state(RB_INPUTED) {}
virtual ~SElliFacCapture() {};
virtual bool PostMouseMsg(HWND, UINT, WPARAM, LPARAM);
virtual void Draw(HDC) const;
private:
enum CREATE_STATE { LT_INPUTED, RB_INPUTED } cur_state;
POINT ptLT, ptRB;
};
class SPolyFacCapture : public FactoryCapture //gather info for creating SPolygon
{
public:
SPolyFacCapture() : cur_state(INPUT_END) {}
virtual ~SPolyFacCapture() {}
virtual bool PostMouseMsg(HWND, UINT, WPARAM, LPARAM);
virtual void Draw(HDC) const;
private:
enum CREATE_STATE { INPUT_POINT, INPUT_END } cur_state;
std::vector<POINT> vecPt;
};
#endif mousecapture.cpp 代码: #include "mousecapture.h"
#include "shapermap.h"
extern ShapeManager sm;
//-------------------------SRectFacCapture methods---------------------------//
void SRectFacCapture::Draw(HDC hdc) const
{
Rectangle(hdc, ptLT.x, ptLT.y, ptRB.x, ptRB.y);
}
bool SRectFacCapture::PostMouseMsg(HWND hwnd, UINT msgMouse, WPARAM wParam, LPARAM lParam)
{
switch (msgMouse)
{
case WM_LBUTTONDOWN:
if (cur_state != RB_INPUTED)
break;
ptLT.x = (int)(LOWORD(lParam));
ptLT.y = (int)(HIWORD(lParam));
cur_state = LT_INPUTED;
break;
case WM_MOUSEMOVE:
if (cur_state != LT_INPUTED)
break;
ptRB.x = (int)(LOWORD(lParam));
ptRB.y = (int)(HIWORD(lParam));
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_LBUTTONUP:
if (cur_state != LT_INPUTED)
break;
ptRB.x = (int)(LOWORD(lParam));
ptRB.y = (int)(HIWORD(lParam));
sm.Add(new SRectMap(SRect(ptLT, ptRB)));
cur_state = RB_INPUTED;
return false;
case WM_RBUTTONUP:
cur_state = RB_INPUTED;
return false;
}
return true;
}
//------------------------------SElliFacCapture methods--------------------------//
void SElliFacCapture::Draw(HDC hdc) const
{
Ellipse(hdc, ptLT.x, ptLT.y, ptRB.x, ptRB.y);
}
bool SElliFacCapture::PostMouseMsg(HWND hwnd, UINT msgMouse, WPARAM wParam, LPARAM lParam)
{
switch (msgMouse)
{
case WM_LBUTTONDOWN:
if (cur_state != RB_INPUTED)
break;
ptLT.x = (int)(LOWORD(lParam));
ptLT.y = (int)(HIWORD(lParam));
cur_state = LT_INPUTED;
break;
case WM_MOUSEMOVE:
if (cur_state != LT_INPUTED)
break;
ptRB.x = (int)(LOWORD(lParam));
ptRB.y = (int)(HIWORD(lParam));
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_LBUTTONUP:
if (cur_state != LT_INPUTED)
break;
ptRB.x = (int)(LOWORD(lParam));
ptRB.y = (int)(HIWORD(lParam));
sm.Add(new SElliMap(SEllipse(ptLT, ptRB)));
cur_state = RB_INPUTED;
return false;
case WM_RBUTTONUP:
cur_state = RB_INPUTED;
return false;
}
return true;
}
//-----------------------------SPolyFacCapture methods------------------------//
void SPolyFacCapture::Draw(HDC hdc) const
{
POINT * ppt = new POINT[vecPt.size()];
for (int i = 0; i < vecPt.size(); ++i)
ppt[i] = vecPt[i];
Polyline(hdc, ppt, vecPt.size());
delete [] ppt;
}
bool SPolyFacCapture::PostMouseMsg(HWND hwnd, UINT msgMouse, WPARAM wParam, LPARAM lParam)
{
POINT ptMouse;
POINT * ppt;
switch (msgMouse)
{
case WM_LBUTTONUP:
ptMouse.x = (int)(LOWORD(lParam));
ptMouse.y = (int)(HIWORD(lParam));
vecPt.push_back(ptMouse);
InvalidateRect(hwnd, NULL, TRUE);
return true;
case WM_RBUTTONUP:
sm.Add(new SPolyMap(SPolygon(vecPt)));
vecPt.clear();
InvalidateRect(hwnd, NULL, TRUE);
return false;
}
return true;
}
//---------------------------MoveCapture methods--------------------------//
bool MoveCapture::PostMouseMsg(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int x, y;
x = (int)(LOWORD(lParam));
y = (int)(HIWORD(lParam));
POINT ptOffset;
switch (message)
{
case WM_LBUTTONDOWN:
cur_state = MOVING;
ptStart.x = x;
ptStart.y = y;
break;
case WM_MOUSEMOVE:
if (cur_state != MOVING)
break;
ptOffset.x = x - ptStart.x;
ptOffset.y = y - ptStart.y;
pShape->Move(ptOffset);
InvalidateRect(hwnd, NULL, TRUE);
ptStart.x = x;
ptStart.y = y;
break;
case WM_LBUTTONUP:
cur_state = END;
ptOffset.x = x - ptStart.x;
ptOffset.y = y - ptStart.y;
pShape->Move(ptOffset);
InvalidateRect(hwnd, NULL, TRUE);
return false;
}
return true;
} shapemain.cpp 代码: #include <windows.h>
#include "mousecapture.h"
#include "shapermap.h"
ShapeManager sm;
FactoryManager fm;
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[ ] = "WindowsApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
#define ID_CRT_RECT 100
#define ID_CRT_ELLI 101
#define ID_CRT_POLY 102
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hCrtRect, hCrtElli, hCrtPoly;
static int cxChar, cyChar;
static HINSTANCE hInstance;
static RECT rcPaint;
PAINTSTRUCT ps;
HDC hdc;
switch (message) /* handle the messages */
{
case WM_CREATE:
cxChar = LOWORD(GetDialogBaseUnits());
cyChar = HIWORD(GetDialogBaseUnits());
hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
hCrtRect = CreateWindow(TEXT("button"),
TEXT("Rectangle"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
15, 20, 12 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU)ID_CRT_RECT,
hInstance, NULL);
hCrtElli = CreateWindow(TEXT("button"),
TEXT("Ellipse"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
15, 70, 12 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU)ID_CRT_ELLI,
hInstance, NULL);
hCrtPoly = CreateWindow(TEXT("button"),
TEXT("Polygon"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
15, 120, 12 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU)ID_CRT_POLY,
hInstance, NULL);
rcPaint.left = 40 + 12 * cxChar;
rcPaint.top = 0;
return 0;
case WM_SIZE:
rcPaint.right = LOWORD(lParam);
rcPaint.bottom = HIWORD(lParam);
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_CRT_RECT:
fm.SetHandle(new SRectFacCapture);
break;
case ID_CRT_ELLI:
fm.SetHandle(new SElliFacCapture);
break;
case ID_CRT_POLY:
fm.SetHandle(new SPolyFacCapture);
break;
}
return 0;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MOUSEMOVE:
if (fm.ExistHandle())
fm.PostMouseMsg(hwnd, message, wParam, lParam);
else
{
if (message == WM_LBUTTONDOWN)
sm.MappingHandle((int)(LOWORD(lParam)), (int)(HIWORD(lParam)));
if (sm.ExistHandle())
sm.PostMouseMsg(hwnd, message, wParam, lParam);
}
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
sm.Draw(hdc);
fm.Draw(hdc);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
}
/* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
} DEVC++下通过编译。提供了鼠标创建图形,移动图形的基本功能,其他有待完善。现在碰到一个算法上的问题,就是怎么判断一个点是在任意的多边形内部呢? |