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 ▭ }
// 旋转拼图块
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 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 // 序列化 void CChip::Serialize(CArchive &ar) { if(ar.IsStoring()) { ar << m_nType; ar << m_nPointCount; for(int i=0; i ar >> m_nType; ar >> m_nPointCount; for(int i=0; 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) 46 // 初始化拼图块 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; pointLis ¨t[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 视 图 类 /////////////////////////////////////////////////// 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) 47 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 // 消息响应:用户点击鼠标左键时调用 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) // 应 用 程 序 类 /////////////////////////////////////////////// 48 #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; 7-23 为例9-3的吹泡泡程序添加一标识符为IDI_MAINICON的图标(该图标应已按11.8:“向项目中添加资源”中的方法建立并加入项目)。 说 明:建立项目的方法见9.8:“用Visual C++集成开发环境开发Win32应用程序”。 程 序: 在例9-3程序前面添加一文件包含命令: #include ”resource.h” 并将CMyApp::InitInstance()函数修改为: BOOL CMyApp::InitInstance() { HICON hIcon; hIcon = LoadIcon(IDI_MAINICON); // 载入图标 CMyWnd *pFrame = new CMyWnd; pFrame->Create(0,_T(\吹泡泡程序\ pFrame->SetIcon(hIcon, TRUE); // 设置大图标 pFrame->SetIcon(hIcon, FALSE); // 设置小图标 pFrame->ShowWindow(m_nCmdShow); this->m_pMainWnd = pFrame; return TRUE; } 7-24 显示一张位图文件(.BMP)。 说 明:首先建立Win32 Application空白项目和源代码文件(不要忘记设置项目使之可以使用MFC类库),然后按11.8:“向项目中添加资源”的方法为项目建立资源文件,并将待显示的位图文件作为资源装入项目。 程 序: // Example 11-2:显示BMP图片 #include class CMyWnd: public CFrameWnd { CBitmap m_Bitmap; int m_nHeight; int m_nWidth; public: CMyWnd(); protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() }; // 消息映射 BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP() // 框架窗口类的成员函数 CMyWnd::CMyWnd() { m_Bitmap.LoadBitmap(IDB_BITMAP1); BITMAP BM; m_Bitmap.GetBitmap(&BM); m_nWidth = BM.bmWidth; m_nHeight = BM.bmHeight; } 49 // 响应绘制窗口客户区消息 void CMyWnd::OnPaint() { CPaintDC dc(this); CDC MemDC; MemDC.CreateCompatibleDC(NULL); MemDC.SelectObject(&m_Bitmap); dc.BitBlt(0,0,m_nWidth,m_nHeight,&MemDC,0,0,SRCCOPY); } // 应用程序类 class CMinMFCApp: public CWinApp { public: BOOL InitInstance(); }; // 应用程序类的成员函数 // 初始化应用程序实例 BOOL CMinMFCApp::InitInstance() { CMyWnd *pFrame = new CMyWnd; pFrame->Create(0,_T(\ pFrame->ShowWindow(m_nCmdShow); this->m_pMainWnd = pFrame; return TRUE; } // 全局应用程序对象 CMinMFCApp ThisApp; 7-25 修改11-2,使之可以不同比例放大或缩小图象。 说 明:使用StretchBlt()函数代替BitBlt()函数就可实现图象的缩放显示。在项目中加入一个弹出式菜单(将标识符改为IDR_MAINMENU),内含3个菜单选项:缩小1倍显示,按原尺寸显示和放大1倍显示,其标识符分别改为ID_SHRINK,ID_BESTFIT和ID_ZOOMOUT。 程 序: // Example 11-3:以不同尺寸显示BMP图片 #include class CMyWnd: public CFrameWnd { CBitmap m_Bitmap; float m_fTimes; int m_nHeight; int m_nWidth; public: CMyWnd(); BOOL PreCreateWindow(CREATESTRUCT &cs); protected: afx_msg void OnPaint(); afx_msg void OnShrink(); afx_msg void OnBestFit(); afx_msg void OnZoomOut(); DECLARE_MESSAGE_MAP() }; // 消息映射 BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd) ON_WM_PAINT() ON_COMMAND(ID_SHRINK, OnShrink) ON_COMMAND(ID_BESTFIT, OnBestFit) ON_COMMAND(ID_ZOOMOUT, OnZoomOut) END_MESSAGE_MAP() // 主窗口类的成员函数 CMyWnd::CMyWnd() { BITMAP BM; m_Bitmap.LoadBitmap(IDB_BITMAP1); m_Bitmap.GetBitmap(&BM); m_nWidth = BM.bmWidth; m_nHeight = BM.bmHeight; m_fTimes = 1.0; } // 装入菜单 BOOL CMyWnd::PreCreateWindow(CREATESTRUCT &cs) { cs.hMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MAINMENU)); return CFrameWnd::PreCreateWindow(cs); } // 缩小图象 void CMyWnd::OnShrink() { m_fTimes = 0.5; Invalidate(); } // 放大图象 void CMyWnd::OnZoomOut() { m_fTimes = 2.0; Invalidate(); } // 原样显示 50