A skeleton demo of mine sweeper, part of the code is developed by Wenjian Luo. ---------------------------------------------------------------- Step 1 Create a project (Mine) using MFC and class wizard. (choose single document). F7 to compile, F5 to debug. Where is main()? ---------------------------------------------------------------- Step 2 Download and insert MineDefs.h Create CMineWnd class using class wizzard. Use the following code to substitute the CMineApp::InitInstance(): >>>>>>>>>>>>>>>>>>> //in Mine.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>> const CString className = _T("MineClass"); BOOL CMineApp::InitInstance() { SetRegistryKey(_T("CSER_513_2")); m_pMineWnd = new CMineWnd(); WNDCLASS wc; ZeroMemory(&wc, sizeof(wc)); wc.hInstance = AfxGetInstanceHandle(); wc.lpfnWndProc = ::DefWindowProc; wc.hbrBackground = NULL; wc.hCursor = LoadCursor(IDC_ARROW); wc.hIcon = LoadIcon(IDR_MAINFRAME); wc.lpszClassName = className; wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); // register the minewnd class //Register the window if (!AfxRegisterClass(&wc)) { AfxMessageBox(_T("Failed to register!")); return FALSE; } // get the minewnd coordinates, width and height UINT uWidth = DEFAULT_FRAME_X + m_uXMineNum * MINE_WIDTH + LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 + SIDE_WIDTH_1; UINT uHeight = DEFAULT_FRAME_Y + m_uYMineNum * MINE_HEIGHT + LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 * 2 + SIDE_WIDTH_1 + SHELL_S_H; UINT uXPos = GetSystemMetrics(SM_CXSCREEN) / 2 - uWidth / 2; UINT uYPos = GetSystemMetrics(SM_CYSCREEN) / 2 - uHeight / 2; //Setup the window if ( !m_pMineWnd->CreateEx( NULL, className, _T("MineSweeper"), WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, uXPos, uYPos, uWidth, uHeight, NULL, NULL) ) { AfxMessageBox(_T("Failed to create the window")); return FALSE; } // Set as the main window m_pMainWnd = m_pMineWnd; //Show the window m_pMineWnd->ShowWindow(SW_NORMAL); return TRUE; } int CMineApp::ExitInstance() { delete m_pMineWnd; return CWinApp::ExitInstance(); } >>>>>>>>>>>>>>>>>>> //in Mine.h >>>>>>>>>>>>>>>>>>>>>>>>>>>> //insert the following into the private section of the class CMineWnd *m_pMineWnd; UINT m_uXMineNum; UINT m_uYMineNum; //insert the following into the public section of the class virtual int ExitInstance(); --------------------------------------------------------------- Step 3 Modify menus, New, Simple, Tops, Exit --------------------------------------------------------------- Step 4 Clean messages (About, etc) in MineApp Add About/Exit in CMinwWnd. >>>>>>>>>>>>>>>>>>>>> //in MineWnd.cpp >>>>>>>>>>>>>>>>>>>>> BEGIN_MESSAGE_MAP(CMineWnd, CWnd) ON_COMMAND(ID_APP_ABOUT, OnMemuAbout) ON_COMMAND(ID_APP_EXIT, OnMemuExit) ON_WM_TIMER() void CMineWnd::OnMemuAbout() { ShellAbout(this->m_hWnd, _T("Mine Sweeper"), _T("Name"), NULL); } void CMineWnd::OnMemuExit() { PostQuitMessage(0); } >>>>>>>>>>>>>>>>>>>>> //in MineWnd.h >>>>>>>>>>>>>>>>>>>>> //add this part before the class definition typedef struct { UINT uRow; //row UINT uCol; //col UINT uState; //current state UINT uAttrib; //attribute UINT uOldState; //prior state } MINEWND; // mine blocks //add in the public part of CMineWnd class afx_msg void OnMemuAbout(); afx_msg void OnMemuExit(); --------------------------------------------------------------- Step 5 Add a dialog box (Highscore) with static text, rename the text with IDC_TXT1 Add a menu iterm to invoke it >>>>>>>>>>>>>>>>>>>>> //in MineWnd.cpp >>>>>>>>>>>>>>>>>>>>> //insert this into MESSAGE_MAP ON_COMMAND(ID_HELP_DIALOG, OnDialog) //insert this in the .cpp file void CMineWnd::OnDialog() { Highscore dlg; dlg.DoModal(); } >>>>>>>>>>>>>>>>>>>>>//in MindWnd.h>>>>>>>>>>>>>>>>>>>>>>>>> //in the public afx_msg void OnDialog(); >>>>>>>>>>>>>>>>>>>>>//in Hihscore.cpp>>>>>>>>>>>>>>>>>>>>>> void Highscore::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); CString str(_T("Mine Sweeper Hero")); DDX_Text(pDX, IDC_TXT1, str); } --------------------------------------------------------------- Step 6 Add new bitmap, change the name to IDB_MINE_COLOR Add CBitMap in CMineWnd Add p_Mines array, create InitGame >>>>>>>>>>>>>>>>>>>>>//in MindWnd.h>>>>>>>>>>>>>>>>>>>>>>>>> //in the private CBitmap m_bmpMine; // Mines UINT m_uXNum; // X numbers of blocks UINT m_uYNum; // Y numbers of blocks RECT m_rcClient; // Mine area CBrush m_brsBG; // Background brush MINEWND m_pMines[100][100]; // array for all mines MINEWND* m_pNewMine; // current block UINT m_uSpendTime; // Game time UINT m_uTimer; // timer CBitmap m_bmpNumber; // bitmap for numbers >>>>>>>>>>>>>>>>>>>>> //in MineWnd.cpp >>>>>>>>>>>>>>>>>>>>> CMineWnd::CMineWnd() { m_brsBG.CreateSolidBrush(COLOR_GRAY); m_uXNum = 10; m_uYNum = 10; m_uTimer = 0; InitGame(); } void CMineWnd::LoadBitmap() { m_bmpMine.DeleteObject(); m_bmpMine.LoadBitmap(IDB_MINE_COLOR); //m_bmpNumber.DeleteObject(); //m_bmpNumber.LoadBitmap(IDB_NUM_COLOR); } void CMineWnd::InitGame() { //init bitmaps LoadBitmap(); m_uSpendTime = 0; if (m_uTimer) { KillTimer(ID_TIMER_EVENT); m_uTimer = 0; } for (UINT i = 0; i>>>>>>>>>>>>>>>>>>>//in MineWnd.cpp >>>>>>>>>>>>>>>>>>>>>>>>>> void CMineWnd::SizeWindow( void ) { UINT uWidth = DEFAULT_FRAME_X + m_uXNum * MINE_WIDTH + LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 + SIDE_WIDTH_1; UINT uHeight = DEFAULT_FRAME_Y + m_uYNum * MINE_HEIGHT + LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 * 2 + SIDE_WIDTH_1 + SHELL_S_H; SetWindowPos(&wndTopMost, 0, 0, uWidth, uHeight, SWP_NOZORDER | SWP_NOMOVE | SWP_NOCOPYBITS); // SWP_NOCOPYBITS does not do function£¿£¿£¿ GetClientRect(&m_rcClient); } void CMineWnd::OnShowWindow(BOOL bShow, UINT nStatus) { SizeWindow(); CWnd::OnShowWindow(bShow, nStatus); } void CMineWnd::OnPaint() { CPaintDC dc(this); // display device CDC dcMemory; // memory device CBitmap bitmap; if (!dc.IsPrinting()) { // compatible with display device if (dcMemory.CreateCompatibleDC(&dc)) { // make bitmap compatible with the actualy dc if (bitmap.CreateCompatibleBitmap(&dc, m_rcClient.right, m_rcClient.bottom)) { // select bitmap dcMemory.SelectObject(&bitmap); //draw background rect dcMemory.FillRect(&m_rcClient, &m_brsBG); //DrawMineArea((CPaintDC&) dcMemory);//draw mine field DrawNumber((CPaintDC&) dcMemory); // copy memory to dc dc.BitBlt(m_rcClient.left, m_rcClient.top, m_rcClient.right, m_rcClient.bottom, &dcMemory, 0, 0, SRCCOPY); bitmap.DeleteObject(); } } } } void CMineWnd::DrawMineArea(CPaintDC &dc) { CDC dcMemory; //memory device dcMemory.CreateCompatibleDC(&dc); //make it compatible with the dc dcMemory.SelectObject(m_bmpMine); //connect bitmap for (UINT i = 0; iuState == STATE_NORMAL) { m_pNewMine->uState = STATE_EMPTY; } Invalidate(); // both of the left button and the right button are pushing down if (nFlags == (MK_LBUTTON | MK_RBUTTON)) { // OnLRBtnDown(m_pOldMine->uRow, m_pOldMine->uCol); } } else { // click in other area } CWnd::OnLButtonDown(nFlags, point); } --------------------------------------------------------------- Step 10 OnTimer, SetTimer --------------------------------------------------------------- Step 11 Draw numbers void CMineWnd::DrawNumber(CPaintDC &dc) { CDC dcMemory; dcMemory.CreateCompatibleDC(&dc); dcMemory.SelectObject(m_bmpNumber); dc.Draw3dRect(16, 15, 41, 25, COLOR_DARK_GRAY, COLOR_WHITE); dc.Draw3dRect(m_rcClient.right - 55, 15, 41, 25, COLOR_DARK_GRAY, COLOR_WHITE); int num; // draw take seconds num = m_uSpendTime / 100; dc.StretchBlt(m_rcClient.right - 55, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY); num = (m_uSpendTime-num*100)/10; dc.StretchBlt(m_rcClient.right - 55 + 13, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY); num = m_uSpendTime%10; dc.StretchBlt(m_rcClient.right - 55+26, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY); }