TanksDlg.cpp
上传用户:royluo
上传日期:2007-01-05
资源大小:1584k
文件大小:19k
源码类别:

游戏

开发平台:

Visual C++

  1. /*****************************************************************************
  2. *                                                                             
  3. *   TanksDlg.cpp
  4. *                                                                             
  5. *   Electrical Engineering Faculty - Software Lab                             
  6. *   Spring semester 1998                                                      
  7. *                                                                             
  8. *   Tanks game                                                                
  9. *                                                                             
  10. *   Module description: Implements the main game dialog.
  11. *                       
  12. *                                                                             
  13. *   Authors: Eran Yariv - 28484475                                           
  14. *            Moshe Zur  - 24070856                                           
  15. *                                                                            
  16. *                                                                            
  17. *   Date: 23/09/98                                                           
  18. *                                                                            
  19. ******************************************************************************/
  20. #include <time.h>
  21. #include "stdafx.h"
  22. #include "Tanks.h"
  23. #include "TanksDlg.h"
  24. #include <GameSetup.h>
  25. #include <GameBoard.h>
  26. #include <TankObj.h>
  27. #include <GameOver.h>
  28. #include <Message.h>
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CAboutDlg dialog used for App About
  36. class CAboutDlg : public CDialog
  37. {
  38. public:
  39.     CAboutDlg();
  40. // Dialog Data
  41.     //{{AFX_DATA(CAboutDlg)
  42.     enum { IDD = IDD_ABOUTBOX };
  43.     //}}AFX_DATA
  44.     // ClassWizard generated virtual function overrides
  45.     //{{AFX_VIRTUAL(CAboutDlg)
  46.     protected:
  47.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  48.     //}}AFX_VIRTUAL
  49. // Implementation
  50. protected:
  51.     //{{AFX_MSG(CAboutDlg)
  52.     //}}AFX_MSG
  53.     DECLARE_MESSAGE_MAP()
  54. };
  55. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  56. {
  57.     //{{AFX_DATA_INIT(CAboutDlg)
  58.     //}}AFX_DATA_INIT
  59. }
  60. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  61. {
  62.     CDialog::DoDataExchange(pDX);
  63.     //{{AFX_DATA_MAP(CAboutDlg)
  64.     //}}AFX_DATA_MAP
  65. }
  66. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  67.     //{{AFX_MSG_MAP(CAboutDlg)
  68.     ON_WM_LBUTTONDOWN()
  69.     //}}AFX_MSG_MAP
  70. END_MESSAGE_MAP()
  71. /////////////////////////////////////////////////////////////////////////////
  72. // CTanksDlg dialog
  73. CTanksDlg::CTanksDlg(CWnd* pParent /*=NULL*/)
  74.     : CDialog(CTanksDlg::IDD, pParent),
  75.       m_GameState (GAME_OFF),
  76.       m_KbdManager(TANKS_APP->m_gKbdManager),
  77.       m_GameManager(TANKS_APP->m_gGameManager)
  78. {
  79.     //{{AFX_DATA_INIT(CTanksDlg)
  80.         // NOTE: the ClassWizard will add member initialization here
  81.     //}}AFX_DATA_INIT
  82.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  83.     m_hIcon = TANKS_APP->LoadIcon(IDR_MAINFRAME);
  84. }
  85. CTanksDlg::~CTanksDlg ()
  86. {
  87.     TANKS_APP->m_gDrawDIB.Close ();
  88. }
  89. void CTanksDlg::DoDataExchange(CDataExchange* pDX)
  90. {
  91.     CDialog::DoDataExchange(pDX);
  92.     //{{AFX_DATA_MAP(CTanksDlg)
  93.     DDX_Control(pDX, IDC_AMMO_STATUS, m_AmmoStatus);
  94.     DDX_Control(pDX, IDC_BONUS_STATUS, m_BonusStatus);
  95.     DDX_Control(pDX, IDC_SHIELD_STATUS, m_ShieldStatus);
  96.     DDX_Control(pDX, IDC_MAP, m_Map);
  97.     //}}AFX_DATA_MAP
  98. }
  99. BEGIN_MESSAGE_MAP(CTanksDlg, CDialog)
  100.     //{{AFX_MSG_MAP(CTanksDlg)
  101.     ON_WM_SYSCOMMAND()
  102.     ON_WM_PAINT()
  103.     ON_WM_QUERYDRAGICON()
  104.     ON_COMMAND(ID_EXIT, OnExit)
  105.     ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout)
  106.     ON_COMMAND(ID_KBD_MAPPING, OnKbdMapping)
  107.     ON_COMMAND(ID_NEW_GAME, OnNewGame)
  108.     ON_COMMAND(ID_SET_COMM, OnSetComm)
  109.     ON_COMMAND(ID_SET_GAME, OnSetGame)
  110.     ON_COMMAND(ID_STOP_GAME, OnStopGame)
  111. ON_COMMAND(ID_SOUND_MUTE, OnSoundMute)
  112.     ON_WM_DRAWITEM()
  113.     ON_WM_CLOSE()
  114.     ON_WM_QUERYNEWPALETTE()
  115.     ON_WM_PALETTECHANGED()
  116.     ON_COMMAND(ID_SERVER_MGMT, OnServerMgmt)
  117.     ON_WM_ERASEBKGND()
  118. ON_COMMAND(ID_PALYERS_GUIDE, OnPlayersGuide)
  119. ON_COMMAND(ID_CHAT_OPEN, OnChatOpen)
  120. //}}AFX_MSG_MAP
  121. END_MESSAGE_MAP()
  122. /////////////////////////////////////////////////////////////////////////////
  123. // CTanksDlg message handlers
  124. BOOL CTanksDlg::OnInitDialog()
  125. {
  126.     CDialog::OnInitDialog();
  127.     // Add "About..." menu item to system menu.
  128.     // IDM_ABOUTBOX must be in the system command range.
  129.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  130.     ASSERT(IDM_ABOUTBOX < 0xF000);
  131.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  132.     if (pSysMenu != NULL)
  133.     {
  134.         CString strAboutMenu;
  135.         strAboutMenu.LoadString(IDS_ABOUTBOX);
  136.         if (!strAboutMenu.IsEmpty())
  137.         {
  138.             pSysMenu->AppendMenu(MF_SEPARATOR);
  139.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  140.         }
  141.     }
  142.     // Set the icon for this dialog.  The framework does this automatically
  143.     //  when the application's main window is not a dialog
  144.     SetIcon(m_hIcon, TRUE);         // Set big icon
  145.     SetIcon(m_hIcon, FALSE);        // Set small icon
  146.         // Allign the main dialog, the map and the status bars
  147.     AlignControls();    
  148.         // Start with the "stop game" menu option disabled
  149.     GetMenu()->EnableMenuItem(ID_STOP_GAME, MF_BYCOMMAND | MF_GRAYED);
  150.     GetMenu()->EnableMenuItem 
  151.         (ID_SERVER_MGMT, TANKS_APP->GetStoredIsHostFlag() ? 
  152.             (MF_BYCOMMAND | MF_ENABLED) : (MF_BYCOMMAND | MF_GRAYED));
  153.         // Start with "chat open" option disabled
  154.     GetMenu()->EnableMenuItem(ID_CHAT_OPEN, MF_BYCOMMAND | MF_GRAYED);
  155.         // Start the image manager
  156.     TANKS_APP->m_gImageManager.LoadImages ();
  157.         // Start the sound manager
  158.     if (! TANKS_APP->m_gSoundManager.Init(m_hWnd))
  159.     {   // Failed to create DirectSound, disable sound menu item:
  160.         GetMenu()->EnableMenuItem(ID_SOUND_MUTE, MF_BYCOMMAND | MF_GRAYED);
  161.             // To be on the safe side :
  162.         TANKS_APP->m_gSoundManager.SetMuteMode(TRUE);   
  163.     } else
  164.     {
  165.         BOOL bMuteMode = TANKS_APP->GetStoredMuteMode();
  166.         GetMenu()->EnableMenuItem(ID_SOUND_MUTE, MF_BYCOMMAND | MF_ENABLED);
  167.         GetMenu()->CheckMenuItem(ID_SOUND_MUTE, 
  168.              bMuteMode ? MF_CHECKED : MF_UNCHECKED);
  169.             // Init the mute mode
  170.         TANKS_APP->m_gSoundManager.SetMuteMode(bMuteMode);   
  171.     }
  172.         // Create status bars
  173.     CreateStatusPanes ();
  174.     StartDIBDrawingEngine ();
  175.     CheckDPlayVersion();
  176.     return TRUE;  // return TRUE  unless you set the focus to a control
  177. }
  178. void CTanksDlg::OnSysCommand(UINT nID, LPARAM lParam)
  179. {
  180.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  181.     {
  182.         CAboutDlg dlgAbout;
  183.         dlgAbout.DoModal();
  184.     }
  185.     else
  186.     {
  187.         CDialog::OnSysCommand(nID, lParam);
  188.     }
  189. }
  190. // If you add a minimize button to your dialog, you will need the code below
  191. //  to draw the icon.  For MFC applications using the document/view model,
  192. //  this is automatically done for you by the framework.
  193. void CTanksDlg::OnPaint() 
  194. {
  195.     if (IsIconic())
  196.     {
  197.         CPaintDC dc(this); // device context for painting
  198.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  199.         // Center icon in client rectangle
  200.         int cxIcon = GetSystemMetrics(SM_CXICON);
  201.         int cyIcon = GetSystemMetrics(SM_CYICON);
  202.         CRect rect;
  203.         GetClientRect(&rect);
  204.         int x = (rect.Width() - cxIcon + 1) / 2;
  205.         int y = (rect.Height() - cyIcon + 1) / 2;
  206.         // Draw the icon
  207.         dc.DrawIcon(x, y, m_hIcon);
  208.     }
  209.     else
  210.     {
  211.         CDialog::OnPaint();
  212.     }
  213. }
  214. // The system calls this to obtain the cursor to display while the user drags
  215. //  the minimized window.
  216. HCURSOR CTanksDlg::OnQueryDragIcon()
  217. {
  218.     return (HCURSOR) m_hIcon;
  219. }
  220. void CTanksDlg::OnExit() 
  221. {
  222.     if (IsGameOn()) {
  223.         UINT uStrInd = TANKS_APP->m_gCommManager.IsHost() 
  224.             ? IDS_HOST_ON_EXIT 
  225.             : IDS_PLAYER_ON_EXIT;
  226.         if (IDNO == AfxMessageBox(uStrInd, MB_YESNO | MB_ICONQUESTION))
  227.             return;
  228.     }
  229.     CDialog::OnCancel();
  230. }
  231. void CTanksDlg::OnHelpAbout() 
  232. {
  233.     CAboutDlg dlgAbout;
  234.     dlgAbout.DoModal();
  235. }
  236. void CTanksDlg::OnKbdMapping() 
  237. {
  238.     TANKS_APP->m_gKbdManager.SetKbdMapping();
  239. }
  240. void CTanksDlg::OnSetComm() 
  241. {
  242.     TANKS_APP->m_gCommManager.SetCommParams();  
  243. }
  244. void CTanksDlg::OnSetGame() 
  245. {
  246.     CGameSetup GameSetupDlg;
  247.     GameSetupDlg.DoModal(); 
  248. }
  249. void CTanksDlg::OnNewGame() 
  250. {
  251.         // Can only be called from GAME_OFF state
  252.     ASSERT (GAME_OFF == m_GameState);
  253.         // Disable "new game" menu item
  254.     GetMenu()->EnableMenuItem(ID_NEW_GAME, MF_BYCOMMAND | MF_GRAYED);
  255.         // Enable "stop game" menu item
  256.     GetMenu()->EnableMenuItem(ID_STOP_GAME, MF_BYCOMMAND | MF_ENABLED);
  257.         // Enable "chat open" menu item
  258.     GetMenu()->EnableMenuItem(ID_CHAT_OPEN, MF_BYCOMMAND | MF_ENABLED);
  259.     TANKS_APP->SetMapHWND( m_Map.m_hWnd );
  260.     if (! TANKS_APP->StartGameThreads ()) {
  261.             // Enable "new game" menu item
  262.         GetMenu()->EnableMenuItem(ID_NEW_GAME, MF_BYCOMMAND | MF_ENABLED);
  263.             // Disable "stop game" menu item
  264.         GetMenu()->EnableMenuItem(ID_STOP_GAME, MF_BYCOMMAND | MF_GRAYED);
  265.         return;
  266.     }
  267.         // Show game controls
  268.     HideGameControl (m_ShieldStatus, FALSE);
  269.     HideGameControl (m_AmmoStatus, FALSE);
  270.     HideGameControl (m_BonusStatus, FALSE);
  271.     m_GameState = GAME_ON;
  272. }
  273. void CTanksDlg::GameOver()
  274. {
  275.         // Can only be called from GAME_ON state
  276.     ASSERT (GAME_ON == m_GameState);
  277.         // Disable "stop game" menu item
  278.     GetMenu()->EnableMenuItem(ID_STOP_GAME, MF_BYCOMMAND | MF_GRAYED);
  279.     m_GameState = GAME_OVER;
  280.         // Disable chat dialog. We can leave it open though, because our tank ID
  281.         // is still occupied:
  282.     GetMenu()->EnableMenuItem(ID_CHAT_OPEN, MF_BYCOMMAND | MF_GRAYED);
  283.         // Add the GameOver animation object to the game:
  284.     CMessage::MessageData DummyParams;
  285.     TANKS_APP->m_gIncomingMsgQueue.Enqueue (CMessage::ADD_GAME_OVER, DummyParams);
  286. }
  287. void CTanksDlg::OnStopGame() 
  288. // Called after the user pressed a key in the "Game-Over" animation sequence
  289. {
  290.         // Can only be called from GAME_OVER or GAME_ONstate
  291.     ASSERT (GAME_OFF != m_GameState);
  292.         // Warn host before we continue:
  293.     if (TANKS_APP->m_gCommManager.IsHost()) {
  294.         if (IDNO == AfxMessageBox(IDS_HOST_ON_STOP, MB_YESNO | MB_ICONQUESTION))
  295.             return;
  296.     }
  297.         // Hide the controls
  298.     HideGameControl (m_ShieldStatus, TRUE);
  299.     HideGameControl (m_AmmoStatus, TRUE);
  300.     HideGameControl (m_BonusStatus, TRUE);
  301.     
  302.         // Enable "new game" menu item
  303.     GetMenu()->EnableMenuItem(ID_NEW_GAME, MF_BYCOMMAND | MF_ENABLED);
  304.         // Disable "stop game" menu item
  305.     GetMenu()->EnableMenuItem(ID_STOP_GAME, MF_BYCOMMAND | MF_GRAYED);
  306.         // Disable "chat open" menu item
  307.     m_ChatDlg.Close();
  308.     GetMenu()->EnableMenuItem(ID_CHAT_OPEN, MF_BYCOMMAND | MF_GRAYED);
  309.     m_GameState = GAME_OFF;
  310.         // Stop player, and close session:
  311.     TANKS_APP->m_gCommManager.OnStopGame();
  312.     TANKS_APP->EndGameThreads();
  313.         // Cause the logo screen to redraw
  314.     m_Map.Invalidate (TRUE);
  315. }
  316. void CTanksDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
  317. {
  318.     CDC *pdc = CDC::FromHandle (lpDrawItemStruct->hDC);
  319.     switch (nIDCtl) {
  320.         case IDC_MAP:   // Draw map region 
  321.             { 
  322.                 if (m_GameState != GAME_OFF)
  323.                 {   // Let the renderer do its job
  324.                     m_GameManager.RefreshDisplay ();
  325.                 }
  326.                 else 
  327.                 {
  328.                     // Now paste the splash screen to the DC please........
  329.                     CDIB dib;
  330.                     if (dib.ReadFromResource (IDB_SPLASH))
  331.                         dib.Paint (pdc);
  332.                 }
  333.             }
  334.             break;
  335.         case IDC_SHIELD_STATUS:
  336.             m_ShieldStatus.GetImage () -> Paint (pdc);
  337.             break;
  338.         case IDC_AMMO_STATUS:
  339.             m_AmmoStatus.GetImage () -> Paint (pdc);
  340.             break;
  341.         case IDC_BONUS_STATUS:
  342.             m_BonusStatus.GetImage () -> Paint (pdc);
  343.             break;
  344.         default:
  345.             CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
  346.             break;
  347.     }
  348. }
  349. void CTanksDlg::AlignControls()
  350. {
  351.     CRect ctlRect, dlgRect;
  352.     GetWindowRect (dlgRect);
  353.     GetClientRect (ctlRect);
  354.     int iExtraRoom = dlgRect.Height() - ctlRect.Height() + 10;
  355.     MoveWindow (dlgRect.left, dlgRect.top, 
  356.                 MAP_WIDTH + 20 + SHIELD_STATUS_WIDTH + AMMO_STATUS_WIDTH,
  357.                 MAP_HEIGHT + iExtraRoom);
  358.     m_ShieldStatus.GetClientRect (ctlRect);
  359.     m_ShieldStatus.MoveWindow ( ctlRect.left + 5,
  360.                                 ctlRect.top + 5, 
  361.                                 SHIELD_STATUS_WIDTH, 
  362.                                 MAP_HEIGHT,
  363.                                 FALSE);
  364.     m_Map.GetClientRect (ctlRect);
  365.     int iMapX = ctlRect.left + 10 + SHIELD_STATUS_WIDTH,
  366.         iMapY = ctlRect.top + 5;
  367.     m_Map.MoveWindow (iMapX, iMapY, MAP_WIDTH, MAP_HEIGHT, FALSE);
  368.     m_AmmoStatus.GetClientRect (ctlRect);
  369.     m_AmmoStatus.MoveWindow (   ctlRect.left + MAP_WIDTH + SHIELD_STATUS_WIDTH + 15, 
  370.                                 ctlRect.top + 5, 
  371.                                 AMMO_STATUS_WIDTH, 
  372.                                 AMMO_STATUS_HEIGHT,
  373.                                 FALSE);
  374.     m_BonusStatus.GetClientRect (ctlRect);
  375.     m_BonusStatus.MoveWindow (  ctlRect.left + MAP_WIDTH + SHIELD_STATUS_WIDTH + 15, 
  376.                                 ctlRect.top + AMMO_STATUS_HEIGHT + 5, 
  377.                                 AMMO_STATUS_WIDTH, 
  378.                                 MAP_HEIGHT - AMMO_STATUS_HEIGHT,
  379.                                 FALSE);
  380. }
  381. BOOL CTanksDlg::OnEraseBkgnd(CDC* pDC) 
  382. {
  383.     // Keep Windows from erasing the background of our map
  384.     if (pDC == m_Map.GetDC())
  385.         return TRUE;
  386.     return CDialog::OnEraseBkgnd (pDC);
  387. }
  388. BOOL 
  389. CTanksDlg::PreTranslateMessage(MSG* pMsg)
  390. {
  391.     if (GAME_OFF != m_GameState)
  392.     {
  393.         // Catch key strokes only if a game is active
  394.         switch (pMsg->message) {
  395.             case WM_KEYDOWN:
  396.             case WM_SYSKEYDOWN:
  397.                 if (GAME_OVER == m_GameState)
  398.                 {
  399.                     // Waiting for any key from the user, and one just arrived.
  400.                     OnStopGame();
  401.                     return TRUE;    // Don't let the dialog have this key
  402.                 }
  403.                 else 
  404.                 {
  405.                     if (m_KbdManager.SetKey(pMsg->wParam) ||
  406.                         (VK_ESCAPE == pMsg->wParam))
  407.                             // Key was successfully mapped to game 
  408.                             // or it was Esc
  409.                         return TRUE;
  410.                     else
  411.                             // We don't know this key => dispatch it to the dialog
  412.                         return FALSE;
  413.                 }
  414.                 break;
  415.             case WM_KEYUP:
  416.             case WM_SYSKEYUP:
  417.                 if (m_KbdManager.UnsetKey(pMsg->wParam) ||
  418.                     (VK_ESCAPE == pMsg->wParam))
  419.                         // Key was successfully mapped to game 
  420.                         // or it was Esc
  421.                     return TRUE;
  422.                 else
  423.                         // We don't know this key => dispatch it to the dialog
  424.                     return FALSE;
  425.                 break;
  426.         }
  427.     }
  428.     return CDialog::PreTranslateMessage(pMsg);
  429. }
  430. void CTanksDlg::HideGameControl(CWnd &ctrl, BOOL bHide)
  431. {
  432.     ctrl.EnableWindow (bHide ? FALSE : TRUE);
  433.     ctrl.ShowWindow (bHide ? SW_HIDE : SW_SHOW);
  434. }
  435. void CTanksDlg::OnClose() 
  436. {
  437.     // Catch application before exiting:
  438.     if (IsGameOn()) {
  439.         UINT uStrInd = TANKS_APP->m_gCommManager.IsHost() 
  440.             ? IDS_HOST_ON_EXIT 
  441.             : IDS_PLAYER_ON_EXIT;
  442.         if (IDNO == AfxMessageBox(uStrInd, MB_YESNO | MB_ICONQUESTION))
  443.             return;
  444.     }   
  445.     CDialog::OnClose();
  446. }
  447. void CTanksDlg::CreateStatusPanes()
  448. {
  449.     m_AmmoStatus.Create ();
  450.     m_BonusStatus.Create ();
  451.     m_ShieldStatus.SetLevel (0);
  452.     m_AmmoStatus.SetShellsCount (0);
  453.     m_AmmoStatus.SetBulletsCount (0);
  454.     m_AmmoStatus.SetMinesCount (0);
  455.     m_BonusStatus.SetAerialSupport (FALSE);
  456.     m_BonusStatus.SetFastFireRate (FALSE);
  457. }
  458. void CTanksDlg::StartDIBDrawingEngine()
  459. {
  460.     TANKS_APP->m_gDrawDIB.Open ();
  461. }
  462. BOOL CTanksDlg::OnQueryNewPalette() 
  463. {
  464.     return TRUE;
  465. }
  466. void CTanksDlg::OnPaletteChanged(CWnd* pFocusWnd) 
  467. {
  468.     if (pFocusWnd != this)
  469.         OnQueryNewPalette ();
  470. }
  471. void CTanksDlg::CheckDPlayVersion()
  472. {
  473. /*  In this function we should check that we can create a DPlay2 interface.
  474.     If not - we should display a detailed dialog to the user, telling him
  475.     that he cannot connect or host a session and point the user to the URL
  476.     where he can download the latest SP (for NT) or DirectX runtime.
  477. */
  478. }
  479. void CTanksDlg::OnOK()
  480. {
  481.     // This function is here to override the default CDialog::OnOK which
  482.     // closes the dialog window  - we don't want that to happen
  483. }
  484. void CTanksDlg::OnServerMgmt() 
  485. {
  486.     if (!(TANKS_APP->GetStoredIsHostFlag()))
  487.         return; // Player is not hosting a game
  488.     m_SrvMgmtDlg.Open (this);
  489. }
  490. void
  491. CTanksDlg::OnChatOpen()
  492. {
  493.     if (m_GameState != GAME_ON)   // We have to have a local tank ID to send chat msg:
  494.         return;
  495.     m_ChatDlg.Open(this);
  496. }
  497. void CTanksDlg::OnPlayersGuide() 
  498. {
  499.     CString cstrHTML = TANKS_APP->m_pszHelpFilePath;
  500.     int i=cstrHTML.ReverseFind ('\');
  501.     cstrHTML = cstrHTML.Left (i);
  502.     cstrHTML += "\HTML\players.htm";
  503.     
  504.     HINSTANCE hRes = ShellExecute ( m_hWnd, 
  505.                                     "open", 
  506.                                     cstrHTML,
  507.                                     NULL,
  508.                                     NULL,
  509.                                     SW_MAXIMIZE);
  510.     if (DWORD(hRes) <= 32)
  511.         AfxMessageBox (IDS_CANT_SHOW_IE, MB_OK);
  512. }            
  513. void 
  514. CTanksDlg::OnSoundMute() 
  515. {
  516.     UINT uFlag = GetMenu()->GetMenuState(ID_SOUND_MUTE, MF_BYCOMMAND);
  517.     if (MF_CHECKED == uFlag)
  518.     {   // The user wants to uncheck (return the game sound):
  519.         GetMenu()->CheckMenuItem(ID_SOUND_MUTE, MF_UNCHECKED);
  520.         TANKS_APP->m_gSoundManager.SetMuteMode(FALSE);
  521.         TANKS_APP->SetStoredMuteMode(FALSE);
  522.     } else if (MF_UNCHECKED == uFlag)
  523.     {   // The user wants to check (mute the game sound):
  524.         GetMenu()->CheckMenuItem(ID_SOUND_MUTE, MF_CHECKED);
  525.         TANKS_APP->m_gSoundManager.SetMuteMode(TRUE);
  526.         TANKS_APP->SetStoredMuteMode(TRUE);
  527.     }
  528. }