[原创+连载]一步一步做拼图游戏,C++版(七)

来源:互联网 发布:在线网络教学 编辑:程序博客网 时间:2024/04/28 01:00

 

这次我们要使游戏更具有游戏性。我们要添加一个菜单。
 
添加菜单
1.   我们要在解决方案管理器中切换到资源视图,然后按下图:
双击Menu里的东西,然后在右边的“请在此键入”里写上想要的东西,然后在属性里改ID
如果没有Menu,就在Puzzle.rc上单击右键,然后“添加资源”,然后选上”Menu”,再点“新建”就有了,然后自己加上各种信息,包括“文件”那些也要自己写了。
2.   改一下Resouce.h文件里的东西,如下图:
先说怎么改,双击打开Resource.h文件,会提示已经打开,是否关闭,点是,如果不可以的话,就把所有打开的资源关闭了再试。然后找到你前面定义的各种菜单ID,看看后面的数字是不是连续的,如果不是,请修改成连续的,但是一定不要和其他的重复了。所以,平时这个文件是不要随便动的。因为我们的程序小,用的资源少才可以这样干的。
再说说原因吧,这个文件从名字上看就是资源文件,我们的资源ID其实就是一个数字,都是宏定义的,写成ID是为了方便使用,所以我们在程序代码里用ID和用数字是一样的效果。改成连续的,我们在后面代码里用的时候就可以用循环了,而不需要每个都写一遍。
写完这个一定要记得把这个文件关了,否则就打不开资源文件了。
设置完以上的这些,代码就比较简单了。我们只是设置一下不同难度下,我们一共有的格子数就OK了。
还记得我们之前的做法,可以让我们设置任意数量的开始局面吗?现在用上了吧。在CPuzzleMain类里添加以下一个函数:
 
Code:
  1. void CPuzzleMain::Menu(int MenuID, HWND hWnd)   
  2. {   
  3.      for(int i=0; i<6; i++)   
  4.      {   
  5.            CheckMenuItem(GetMenu(hWnd), IDM_BEGINER-i, MF_UNCHECKED);//设置为不选中  
  6.      }   
  7.      CheckMenuItem(GetMenu(hWnd), MenuID, MF_CHECKED);   
  8.      int BlockNum = 9-(MenuID-IDM_EXPERT)-1;//设置有多少块,因为我这里是专家级的最小,根据实际情况来。  
  9.      m_Logic.InitLogic(BlockNum);   
  10.      m_View.InitView(hWnd, BlockNum);   
  11.      m_View.LoadBMPList(m_Logic.GetBlock());   
  12.      m_View.SetGameStarted(true);   
  13.      m_Logic.SetGamePlaying(true);   
  14. }   
参数一个是菜单的ID,就是我们之前设置的那些,在资源管理器里设置的。第二个是应用程序句柄。
Code:
  1. for(int i=0; i<6; i++)   
  2.      {   
  3.            CheckMenuItem(GetMenu(hWnd), IDM_BEGINER-i, MF_UNCHECKED);//设置为不选中  
  4.      }   
这里,就用到了我们之前的ID的数字是连续的,所以循环就可以实现了,否则就一个一个写,我这里就要写6个。
CheckMenuItem函数有三个参数,第一个是菜单的句柄,用GetMenu()获取到的。第二个是要修改的菜单项的ID。第三个是怎么处理,我这里是不选中。
再然后是根据等级来设置所分的块数。
      CheckMenuItem(GetMenu(hWnd), MenuID, MF_CHECKED);
      int BlockNum = 9-(MenuID-IDM_EXPERT)-1;//设置有多少块,因为我这里是专家级的最小,根据实际情况来。
一共6个等级,最低的是3*3的,最高的是8*8的。所以用上面的减法就可以算出是多少块。
再往下就是初始化的部分了,和以前的一样,就不多说了,多亏了以前留下的好方法,可以随便改。
现在我们有了菜单要做的事情,但是怎么触发呢?呵呵,这就是Windows的消息机制了。
打开Puzzle.cpp就是系统自动生成的那个,有main的那个。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
这个函数是消息处理函数,我们所有的消息都在这里,我们重点看以下的部分:
Code:
  1. switch (message)   
  2.       {   
  3.       case WM_COMMAND:   
  4.            wmId    = LOWORD(wParam);   
  5.            wmEvent = HIWORD(wParam);   
  6.            // 分析菜单选择:   
  7.            switch (wmId)   
  8.            {   
  9.            case IDM_ABOUT:   
  10.                  DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);   
  11.                  break;   
  12.            case IDM_EXIT:   
  13.                  DestroyWindow(hWnd);   
  14.                  break;   
  15.            case IDM_BEGINER:   
  16.            case IDM_PRIMER:   
  17.            case IDM_THRESHOLD:   
  18.            case IDM_MIDDLE:   
  19.            case IDM_HIGH:   
  20.            case IDM_EXPERT:   
  21.                  g_PuzzleMain.Menu(wmId, hWnd);   
  22.                  break;   
  23.            default:   
  24.                  return DefWindowProc(hWnd, message, wParam, lParam);   
  25.            }   
  26.            break;   
  27. ……   
当然我们省略了很多,这里有两个swtich,第一个switch是消息的类别,case WM_COMMAND:指的就是菜单消息,也就是说单击的是菜单的某项时,就触发这个消息。
Code:
  1. wmId    = LOWORD(wParam);   
  2. wmEvent = HIWORD(wParam);  
这两个是取高位和低位,两个里保存的东西是不一样的,这里我们只要用到低位的就可以了,它表示的是具体哪项菜单项。
Code:
  1. case IDM_ABOUT:   
  2.       DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);   
  3.       break;   
  4. case IDM_EXIT:   
  5.       DestroyWindow(hWnd);   
  6.       break;  
这两个是系统自动写的,一个是about窗口的显示,一个是单击了退出后的。
我们要写的是后面的部分。
Code:
  1. case IDM_BEGINER:   
  2. case IDM_PRIMER:   
  3. case IDM_THRESHOLD:   
  4. case IDM_MIDDLE:   
  5. case IDM_HIGH:   
  6. case IDM_EXPERT:   
  7.       g_PuzzleMain.Menu(wmId, hWnd);   
  8.       break;  
这些是说让我们点的那些都进入到g_PuzzleMain对象的Menu函数里去执行相关操作。
这样的话,我们又多了难度选择,不过,开始的时候,菜单里没有一个打钩的,这怎么能行?所以在CPuzzleMain类里的Init函数里添加一句CheckMenuItem(GetMenu(hWnd), IDM_BEGINER, MF_CHECKED);//设置为选中菜鸟,这样开始的时候就有选择上菜鸟级了。
赶快试试吧。
代码下载:download.csdn.net/source/2978264
原创粉丝点击