針對「飛機大戰」類遊戲,在設定對話框中添加「無敵」「無限能量」按鈕,點擊即時修改主遊戲數據,並解決「需點四次才能關閉」的常見問題。
Resource View → 對話框資源 IDD_DIALOG_SETTINGS。IDC_BTN_INVINCIBLE、IDC_BTN_INFINITE_ENERGY、IDC_BTN_CLOSE右鍵對話框類 CSettingsDlg → Add Variable:
m_btnInvincible (CButton)、m_btnInfiniteEnergy、m_btnClose右鍵 → Add Event Handler:
OnBnClickedBtnInvincible 等三個處理函數。// SettingsDlg.cpp
#include "GameData.h" // 單例或全局遊戲數據頭文件
void CSettingsDlg::OnBnClickedBtnInvincible()
{
// 直接修改同進程內的遊戲數據
CGameData::GetInstance()->SetInvincible(true);
AfxMessageBox(_T("無敵模式已開啟"));
}
void CSettingsDlg::OnBnClickedBtnInfiniteEnergy()
{
CGameData::GetInstance()->SetEnergy(99999);
AfxMessageBox(_T("能量已設為無限"));
}
void CSettingsDlg::OnBnClickedBtnClose()
{
// 正確關閉模態對話框
OnOK(); // 或 EndDialog(IDOK);
}
MFC 對話框與主遊戲視圖/文檔運行在同一進程,通過:
CGameData::GetInstance()theApp 全局指針訪問 CGameDocAfxGetMainWnd() 轉型獲取主框架即可直接讀寫任何非私有成員。若成員為 private,添加公有 Set/Get 接口或聲明 friend。
原因:在 OnOK/OnCancel 中誤調用了多次 EndDialog,或按鈕屬性設置為「默認按鈕」導致重複觸發。
// 錯誤示範
void CSettingsDlg::OnBnClickedBtnClose()
{
OnOK(); // 第一次
EndDialog(IDOK); // 第二次 → 導致棧展開異常
CDialogEx::OnOK(); // 第三次
}
// 正確:只調用一次
void CSettingsDlg::OnBnClickedBtnClose()
{
OnOK(); // 模態對話框標準關閉流程
}
檢查資源編輯器中「確定」按鈕的 Default Button 屬性,確保只有一個按鈕勾選。
TRACE(_T(\"Invincible=%d\\n\"), val); 輸出調試信息到 Output 窗口。CGameData 是否真為單例(構造函數 private、靜態實例指針)。