Мое приложение имеет несколько окон, каждое из CDialog
класс.
Нажатие кнопки «X» в верхнем правом углу оконной рамы закрывает окно и вызывает PostNcDestroy
,
Для одного из четырех окон, однако, он также вызывает другое окно PostNcDestroy
() и делает это окно невидимым.
Есть идеи?
Вы не дали много информации. Мы можем только догадываться … Поскольку вы утверждаете, что все ваши окна являются диалогами, я предполагаю, что внутри метода InitInstance () вашего приложения у вас есть вызов DoModal () основного производного класса CDialog. После закрытия главного диалога он выходит из цикла DoModal (), а затем выходит из InitInstance () и закрывает приложение. Завершение работы приложения приводит к разрушению других диалогов, в результате чего отправляется WM_NCDESTROY, а затем вызывается PostNcDestroy ().
КРАТКИЙ ОТВЕТ: поведение было вызвано настройкой m_pMainWnd
ПОСЛЕ создания всех четырех окон. Если он установлен до создания второго окна, проблема выше не возникает.
ДЛИННЫЙ ОТВЕТ: проблема в том, что окна НЕ ИМЕЮТ друг на друга. Каждый из них — РЕБЕНОК ПРЕДЫДУЩЕГО.
Родителем окна 1 является значение «0» (рабочий стол).
Родителем окна 2 является окно 1.
Родителем окна 3 является окно 2.
Родителем окна 4 является окно 3.
В моем первоначальном отчете о проблеме отмечалось, что окно 4 загадочно закрывается, когда окно 3 закрывается Так что теперь причина, почему это очевидно. (Закрытие окна также закрывает все его дочерние элементы.) Впоследствии я обнаружил, что закрытие окна 2 также приводит к закрытию 3 и 4, что также учитывается. (3 является дочерним 2, поэтому закрывается, и это делает 4, который является дочерним 3, закрыт.) Наконец, закрытие окна 1 проверяет несохраненную работу, и если ни один не вызывает exit()
, Я предполагаю, что если бы это окно не выходило, другие окна тоже были бы закрыты.
CDialog::Create()
имеет параметр по умолчанию NULL
за второй аргумент pParentWnd
, а также NULL
означает «родитель» установлен в главном окне приложения. Шагая в CDialog::Create()
, который вызывает CDialog::CreateIndirect()
, который вызывает AfxGetMainWnd()
Я в конечном итоге CWinThread::GetMainWnd()
, Этот метод, если m_pMainWnd
еще не установлено, просто возвращается CWnd::GetActiveWindow()
который является самым недавно созданным окном.
Итак: источник проблемы в том, что мое приложение создало четыре окна, ТО m_pMainWnd
, Вот почему окно 3 было дочерним по отношению к окну 2 (активное окно в этой точке) 4 является дочерним по отношению к 3, и так далее.
Установив m_pMainWnd
после создания окна 1 окна 2, 3 и 4 являются дочерними элементами 1. Таким образом, это избавляет от проблемы «закрытие окна 3 делает окно 4 слишком закрытым».
Это все еще не совсем то, что мне было нужно, так как оно предотвращает появление окна 1 перед остальными тремя окнами. Это выходит за рамки моего первоначального вопроса, но здесь есть исправление. Изменение Create()
позвонить, чтобы пройти GetDesktopWindow()
очевидно, что приложение работает так, как я хотел, с четырьмя окнами, которые могут закрываться независимо друг от друга и свободно настраиваться в стеке окон:
Create( resource_ID, GetDesktopWindow() );
Я удивлен, что это не известная проблема, так как документация (по состоянию на VS2008Pro) для НИХ из этих функций фактически объясняет, что они на самом деле делают, когда m_pMainWnd
не установлен, и перемещение этого простого назначения m_pMainWnd
до конца создания окна, вероятно, испортит ЛЮБОЕ приложение, которое создало более двух окон …