附录5,七巧板程序
// Example 13-7,七巧板程序 //////////////////////////////////
#include <afxwin.h>
#include <afxext.h>
// 拼板类 ////////////////////////////////////////////////////
#define MAX_POINTS 4
#define CHIP_WIDTH 240
#define DELTA 30
class CChip,public CObject
{
DECLARE_SERIAL(CChip)
int m_nType;
CPoint m_pointList[MAX_POINTS];
int m_nPointCount;
public:
CChip(){}
void SetChip(int type,POINT *ppointlist,int count);
void DrawChip(CDC *pDC);
BOOL PtInChip(POINT point);
LPCRECT GetRect();
void MoveTo(CSize offset);
void Rotation();
void Serialize(CArchive &ar);
};
IMPLEMENT_SERIAL(CChip,CObject,1)
// 设置拼图块参数
void CChip::SetChip(int type,POINT *ppointlist,int count)
{
m_nType = type;
m_nPointCount = count;
for(int i=0; i<count; i++)
m_pointList[i] = ppointlist[i];
}
// 绘出拼图块
void CChip::DrawChip(CDC *pDC)
{
CPen penNew,*ppenOld;
CBrush brushNew,*pbrushOld;
switch(m_nType)
{
case 1:
brushNew.CreateSolidBrush(RGB(127,127,127));
break;
case 2:
brushNew.CreateSolidBrush(RGB(255,0,0));
break;
case 3:
brushNew.CreateSolidBrush(RGB(0,255,0));
break;
case 4:
brushNew.CreateSolidBrush(RGB(0,0,255));
break;
case 5:
brushNew.CreateSolidBrush(RGB(127,127,0));
break;
case 6:
brushNew.CreateSolidBrush(RGB(127,0,127));
break;
case 7:
brushNew.CreateSolidBrush(RGB(0,127,127));
break;
}
penNew.CreatePen(PS_SOLID,1,RGB(0,0,0));
ppenOld = pDC->SelectObject(&penNew);
pbrushOld = pDC->SelectObject(&brushNew);
pDC->Polygon(m_pointList,m_nPointCount);
pDC->SelectObject(ppenOld);
pDC->SelectObject(pbrushOld);
}
// 检测一点是否在拼图块中
BOOL CChip::PtInChip(POINT point)
{
CRgn rgn;
rgn.CreatePolygonRgn(m_pointList,m_nPointCount,0);
return rgn.PtInRegion(point);
}
// 取拼图块的包含矩形
LPCRECT CChip::GetRect()
{
static RECT rect;
CRgn rgn;
rgn.CreatePolygonRgn(m_pointList,m_nPointCount,0);
rgn.GetRgnBox(&rect);
rect.right++;
rect.bottom++;
return &rect;
}
// 旋转拼图块
void CChip::Rotation()
{
CRect rect;
CRgn rgn;
rgn.CreatePolygonRgn(m_pointList,m_nPointCount,0);
rgn.GetRgnBox(&rect);
double x = rect.left+rect.Width()/2; // 计算旋转中心
double y = rect.top+rect.Height()/2;
double dx,dy;
for(int i=0; i<m_nPointCount; i++) // 旋转各点
{
dx = m_pointList[i].x-x;
dy = m_pointList[i].y-y;
m_pointList[i].x = (int)(x+dx*0.7071-dy*0.7071);
m_pointList[i].y = (int)(y+dx*0.7071+dy*0.7071);
}
}
// 移动拼图块
void CChip::MoveTo(CSize offset)
{
for(int i=0; i<m_nPointCount; i++)
m_pointList[i] = m_pointList[i]+offset;
}
// 序列化
void CChip::Serialize(CArchive &ar)
{
if(ar.IsStoring())
{
ar << m_nType;
ar << m_nPointCount;
for(int i=0; i<m_nPointCount; i++)
ar << m_pointList[i];
}
else
{
ar >> m_nType;
ar >> m_nPointCount;
for(int i=0; i<m_nPointCount; i++)
ar >> m_pointList[i];
}
}
// 文档类 ////////////////////////////////////////////////////
#define CHIP_COUNT 7
class CMyDoc,public CDocument
{
DECLARE_DYNCREATE(CMyDoc)
CChip m_chipList[CHIP_COUNT];
public:
void Reset();
virtual void DeleteContents();
virtual void Serialize(CArchive& ar);
};
IMPLEMENT_DYNCREATE(CMyDoc,CDocument)
// 初始化拼图块
void CMyDoc::Reset()
{
POINT pointList[MAX_POINTS];
pointList[0].x = DELTA;
pointList[0].y = DELTA;
pointList[1].x = DELTA+CHIP_WIDTH;
pointList[1].y = DELTA;
pointList[2].x = DELTA+CHIP_WIDTH/2;
pointList[2].y = DELTA+CHIP_WIDTH/2;
m_chipList[0].SetChip(1,pointList,3);
pointList[0].x = DELTA;
pointList[0].y = DELTA;
pointList[1].x = DELTA;
pointList[1].y = DELTA+CHIP_WIDTH;
pointList[2].x = DELTA+CHIP_WIDTH/2;
pointList[2].y = DELTA+CHIP_WIDTH/2;
m_chipList[1].SetChip(2,pointList,3);
pointList[0].x = DELTA+CHIP_WIDTH;
pointList[0].y = DELTA;
pointList[1].x = DELTA+CHIP_WIDTH;
pointList[1].y = DELTA+CHIP_WIDTH/2;
pointList[2].x = DELTA+(CHIP_WIDTH*3)/4;
pointList[2].y = DELTA+CHIP_WIDTH/4;
m_chipList[2].SetChip(3,pointList,3);
pointList[0].x = DELTA+CHIP_WIDTH/2;
pointList[0].y = DELTA+CHIP_WIDTH/2;
pointList[1].x = DELTA+CHIP_WIDTH/4;
pointList[1].y = DELTA+(CHIP_WIDTH*3)/4;
pointList[2].x = DELTA+(CHIP_WIDTH*3)/4;
pointList[2].y = DELTA+(CHIP_WIDTH*3)/4;
m_chipList[3].SetChip(4,pointList,3);
pointList[0].x = DELTA+CHIP_WIDTH;
pointList[0].y = DELTA+CHIP_WIDTH/2;
pointList[1].x = DELTA+CHIP_WIDTH;
pointList[1].y = DELTA+CHIP_WIDTH;
pointList[2].x = DELTA+CHIP_WIDTH/2;
pointList[2].y = DELTA+CHIP_WIDTH;
m_chipList[4].SetChip(5,pointList,3);
pointList[0].x = DELTA+(CHIP_WIDTH*3)/4;
pointList[0].y = DELTA+CHIP_WIDTH/4;
pointList[1].x = DELTA+CHIP_WIDTH/2;
pointList[1].y = DELTA+CHIP_WIDTH/2;
pointList[2].x = DELTA+(CHIP_WIDTH*3)/4;
pointList[2].y = DELTA+(CHIP_WIDTH*3)/4;
pointList[3].x = DELTA+CHIP_WIDTH;
pointList[3].y = DELTA+CHIP_WIDTH/2;
m_chipList[5].SetChip(6,pointList,4);
pointList[0].x = DELTA;
pointList[0].y = DELTA+CHIP_WIDTH;
pointList[1].x = DELTA+CHIP_WIDTH/4;
pointList[1].y = DELTA+(CHIP_WIDTH*3)/4;
pointList[2].x = DELTA+(CHIP_WIDTH*3)/4;
pointList[2].y = DELTA+(CHIP_WIDTH*3)/4;
pointList[3].x = DELTA+CHIP_WIDTH/2;
pointList[3].y = DELTA+CHIP_WIDTH;
m_chipList[6].SetChip(7,pointList,4);
}
// 清理文档:关闭文档、建立新文档和打开文档前调用
void CMyDoc::DeleteContents()
{
Reset();
CDocument::DeleteContents();
}
// 系列化:读写文档时自动调用
void CMyDoc::Serialize(CArchive &ar)
{
for(int i=0; i<CHIP_COUNT; i++)
m_chipList[i].Serialize(ar);
}
// 视图类 ///////////////////////////////////////////////////
class CMyView,public CView
{
DECLARE_DYNCREATE(CMyView)
BOOL m_bCaptured;
CPoint m_pointMouse;
int m_nCurrIndex;
public:
CMyView(){m_bCaptured = FALSE;}
CMyDoc* GetDocument(){return (CMyDoc*)m_pDocument;}
virtual void OnInitialUpdate();
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnDraw(CDC* pDC);
afx_msg void OnLButtonDown(UINT nFlags,CPoint point);
afx_msg void OnLButtonUp(UINT nFlags,CPoint point);
afx_msg void OnMouseMove(UINT nFlags,CPoint point);
afx_msg void OnRButtonDown(UINT nFlags,CPoint point);
DECLARE_MESSAGE_MAP()
};
IMPLEMENT_DYNCREATE(CMyView,CView)
BEGIN_MESSAGE_MAP(CMyView,CView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_FILE_PRINT,CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT,CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView::OnFilePrintPreview)
END_MESSAGE_MAP()
// 更新初始化:当建立新文档或打开文档时调用
void CMyView::OnInitialUpdate()
{
CView::OnInitialUpdate();
Invalidate();
}
// 绘制视图:程序开始运行或窗体发生变化时自动调用
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int i=0; i<CHIP_COUNT; i++)
pDoc->m_chipList[i].DrawChip(pDC);
}
// 消息响应:用户点击鼠标左键时调用
void CMyView::OnLButtonDown(UINT nFlags,CPoint point)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int i=CHIP_COUNT-1; i>=0; i--)
if(pDoc->m_chipList[i].PtInChip(point))
{
SetCapture();
m_bCaptured = TRUE;
m_pointMouse = point;
m_nCurrIndex = i;
break;
}
}
// 释放鼠标左键
void CMyView::OnLButtonUp(UINT nFlags,CPoint point)
{
if(m_bCaptured)
{
::ReleaseCapture();
m_bCaptured = FALSE;
}
}
// 移动鼠标左键
void CMyView::OnMouseMove(UINT nFlags,CPoint point)
{
if(m_bCaptured)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
InvalidateRect(pDoc->m_chipList[m_nCurrIndex].GetRect());
CSize offset(point-m_pointMouse);
pDoc->m_chipList[m_nCurrIndex].MoveTo(offset);
InvalidateRect(pDoc->m_chipList[m_nCurrIndex].GetRect());
m_pointMouse = point;
pDoc->SetModifiedFlag();
}
}
// 按下鼠标右键,旋转拼图块
void CMyView::OnRButtonDown(UINT nFlags,CPoint point)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int i=CHIP_COUNT-1; i>=0; i--)
if(pDoc->m_chipList[i].PtInChip(point))
{
InvalidateRect(pDoc->m_chipList[i].GetRect());
pDoc->m_chipList[i].Rotation();
InvalidateRect(pDoc->m_chipList[i].GetRect(),FALSE);
pDoc->SetModifiedFlag();
break;
}
}
// 准备打印:设置打印参数
BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo)
{
pInfo->SetMaxPage(1);
return DoPreparePrinting(pInfo);
}
// 主框架类 //////////////////////////////////////////////////
class CMainFrame,public CFrameWnd
{
DECLARE_DYNCREATE(CMainFrame)
};
IMPLEMENT_DYNCREATE(CMainFrame,CFrameWnd)
// 应用程序类 ///////////////////////////////////////////////
#define IDR_MAINFRAME 128 // 主框架的资源代号
class CMyApp,public CWinApp
{
public:
virtual BOOL InitInstance();
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMyApp,CWinApp)
ON_COMMAND(ID_FILE_NEW,CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN,CWinApp::OnFileOpen)
ON_COMMAND(ID_FILE_PRINT_SETUP,CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
// 初始化程序实例:建立并登记文档模板
BOOL CMyApp::InitInstance()
{
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
return TRUE;
}
// 全局应用程序对象
CMyApp theApp;