Я создал приложение MFC с Base Dialog
(производным от CDialog
класса), Setting Dialog
(производным от CBaseDlg
и App Dialog
(также производным от CBaseDlg
). ЗатемЯ создал класс с именем CScrMng
(он же Screen Manager), который содержит функцию ShowDialog()
(для Create
и Show
этих диалогов).
Основная идея - ScrMng
будет управлять всемимои немодальные диалоги, и в любое время, когда я хочу открыть диалоговое окно, мне просто нужно CScrMng::ShowDialog()
в BaseDlg.cpp
, и диалоговое окно отобразится.
Этот подход вызвал утечку ресурсов здесь и там.Я провел небольшое исследование о переопределении PostNcDestroy()
, но у меня нет четкого представления о том, где его вызвать.
Какую функцию я должен использовать, чтобы правильно закрыть эти немодальные диалоги?
Я хочу открыть Setting Dialog
из Base Dialog
, затем, когда я нажимаю кнопку Cancel
, он должен вернуть меня к экрану Base Dialog
, чтобы я мог открыть другой диалог.
Прямо сейчас я использую EndDialog()
. Я знаю, что это неправильно, но вызов DestroyWindow()
немедленно выйдет из программы,что не то, что я хочу.
Исходный код
MFCApplication.cpp
#include...
BEGIN_MESSAGE_MAP(CMFCApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
CMFCApp::CMFCApp()
{
// support Restart Manager
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
}
CMFCApp theApp;
BOOL CMFCApp::InitInstance()
{
...
CWinApp::InitInstance();
CShellManager *pShellManager = new CShellManager;
CScrMng::GetInstance()->ShowDialog(IDD_MAINDLG);
SetRegistryKey(_T("Local Applications"));
if (pShellManager != NULL)
{
delete pShellManager;
}
return TRUE;
}
CScrMng.cpp
#include...
CScrMng* CScrMng::m_pInstance = NULL;
CScrMng* CScrMng::GetInstance(){
if (m_pInstance == NULL)
m_pInstance = new CScrMng();
return m_pInstance;
}
CScrMng::CScrMng(){}
void CScrMng::ShowDialog(int ID)
{
CMainDlg* m_pDlg = NULL;
switch (ID)
{
case IDD_MAINDLG:
m_pDlg = new CMainDlg();
theApp.m_pMainWnd = m_pDlg;
m_pDlg->Create(IDD_MAINDLG);
m_pDlg->ShowWindow(SW_SHOW);
m_pDlg->UpdateWindow();
break;
case ...
break;
case IDD_SETTINGDLG:
m_pDlg = new CSettingDlg();
m_pDlg->Create(ID,NULL);
m_pDlg->ShowWindow(SW_SHOW);
m_pDlg->UpdateWindow();
break;
}
CMainDlg.cpp
#include...
CMainDlg::CMainDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMainDlg::IDD, pParent) {m_hIcon = AfxGetApp()-> LoadIcon(IDR_MAINFRAME);}
void CMainDlg::DoDataExchange(CDataExchange* pDX) {...}
void CMainDlg::PostNcDestroy() //Added these
{
CDialog::PostNcDestroy();
delete this;
}
BEGIN_MESSAGE_MAP(CMainDlg, CDialog)
...
END_MESSAGE_MAP()
BOOL CMainDlg::OnInitDialog() {
CDialog::OnInitDialog();
SetIcon(m_hIcon, FALSE);
return TRUE;
}
void CMainDlg::OnPaint() {...}
void CMainDlg::OnBnClickedOpenAppdlg()
{
CScrMng::GetInstance()->ShowDialog(IDD_APPDLG);
}
void CMainDlg::OnBnClickedOpenSettingdlg()
{
CScrMng::GetInstance()->ShowDialog(IDD_SETTINGDLG);
}
void CMainDlg::OnBnClickedExit()
{
DestroyWindow(); //replaced CDialog::OnCancel() with this.
}
Обновление: после изменения кода в SettingDlg.cpp я столкнулся с проблемой Debug Assertion Failed!
:
void CWnd::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint)
{
ASSERT(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL)); //Breakpoint triggered
if (m_pCtrlSite == NULL)
::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint);
else
m_pCtrlSite->MoveWindow(x, y, nWidth, nHeight);
}
Вот что я изменил в.файл cpp: SettingDlg.cpp
void CSettingDlg::PostNcDestroy()
{
CMainDlg::PostNcDestroy();
}
void CSettingDlg::OnBnClickedSettingcancel()
{
DestroyWindow(); //Using destroyWindow rather than EndDialog();
}