Поделиться через


TN017: Уничтожение объекты окна

Эта заметка описывает использование метода CWnd::PostNcDestroy.Используйте этот метод, если требуется сделать настраиванное распределение объекты, унаследованные от CWnd.Эта заметка также объясняет, почему следует использовать CWnd::DestroyWindow для уничтожения объекта окон C++ вместо оператора delete.

Если следовать рекомендациям в этом разделе, будет иметь несколько проблем очистки.Эти проблемы могут вызвать из проблем, как забывать удаление и память свободена C++, забывать освободить системные ресурсы, как HWND s или освобождение объекты слишком много раз.

Проблема

Каждый объект windows (объект класса, производного от CWnd) представляет объект C++ и HWND.Объекты C++, выбранные в куче приложения и HWND s видно из системных ресурсов диспетчером окон.Так как несколько способов уничтожить объект окна, необходимо предоставить набор правил, которые препятствуют системный ресурс или утечку памяти.Эти правила также необходимо предотвратить объекты и дескрипторы окна от уничтожения более одного раза.

Уничтожение окна

Следующие 2, разрешенных способа удалить объект окон:

  • Вызов CWnd::DestroyWindow или такой API DestroyWindow windows.

  • Явное удаление с оператором delete.

Первый вариант значительно более общим.Это случай применяется даже в том случае, если код не вызывает DestroyWindow напрямую.Когда пользователь закрывает окно фрейма непосредственно это действие создает сообщение WM_CLOSE и по умолчанию ответа на это сообщение вызова DestroyWindow. при уничтожении окна родительского окна вызывает DestroyWindow для всех ее дочерних элементов.

Второй случай, использование оператора delete на объектах windows, должно иметь редко.Ниже приведены некоторые случаи, когда использование delete правильный выбор.

Автоматическая очистка с CWnd::PostNcDestroy

Когда система удаляет окно windows, последнее сообщение, отправленное в окно WM_NCDESTROY windows.Используемый по умолчанию обработчик CWnd для этого сообщения CWnd::OnNcDestroy.Удаляет из объекта OnNcDestroy наконец HWND C++ и вызывает виртуальная функция PostNcDestroy.Некоторые классы, переопределяют эту функцию для удаления объекта C++.

Реализация по умолчанию не выполняет никаких действий, CWnd::PostNcDestroy, подходящее для объектов окна, выбранные на кадре стека или внедрены в других объектах.Это не подходит для объектов окна, которые предназначены выделенным в куче, причем других объектов.Иначе говоря, не подходит для объектов окна, не внедряются в других объектах C++.

Эти классы, которые предназначены только выбранным в переопределенном методе кучи PostNcDestroy метод для выполнения delete this.Это выписка освободит любая память, связанную с объектом C++.Даже если деструктор CWnd значения по умолчанию вызывает DestroyWindow если m_hWnd, отличное от null, то это не приведет к инфинитной рекурсии, поскольку дескриптор будет удален и наконец NULL на этапе очистки.

ПримечаниеПримечание

Система обычно вызывает CWnd::PostNcDestroy после того, как она обрабатывает сообщение WM_NCDESTROY окон и HWND и объект окна C++ больше не подключены.Кроме того, система вызывает CWnd::PostNcDestroy в реализации большинство вызовов CWnd::Create если произошел сбой.Автоматические правила очистки описаны далее в этом разделе.

Автоматические классы очистки

Следующие классы не предназначены для автоматическ-очистки.Они, как правило, внедренных в других объектах C++ или в стеке.

  • Все элементы управления windows (CStatic standard, CEdit, CListBox и т д).

  • Все дочерние окна, полученные непосредственно из CWnd (например, пользовательских элементов управления).

  • Окна Splitter (CSplitterWnd).

  • По умолчанию панель элементов управления (классы, производные от CControlBar см. в разделе Техническая примечание 31 для разрешения автоматическ-удалить для объектов панели элементов управления).

  • Диалоговые окна (CDialog), разработанные для модальных диалоговых окон в кадре стека.

  • Все стандартные диалоговые окна, за CFindReplaceDialog.

  • По умолчанию диалоги, созданные ClassWizard.

Следующие классы предназначены для автоматическ-очистки.Они обычно выбирается сами по себе в куче:

  • Окна главного фрейма (напрямую или косвенно, производные от CFrameWnd).

  • Окна представления (напрямую или косвенно, производные от CView).

Если требуется прервать эти правила, необходимо переопределить метод PostNcDestroy в производном классе.Чтобы добавить автоматическ-очистка к классу, вызовите свой базовый класс, а затем выполните delete this.Чтобы удалить автоматическ-очистка от класса, вызовите CWnd::PostNcDestroy напрямую вместо метода PostNcDestroy своего непосредственного базового класса.

Чаще всего используется для изменения автоматического расширения функциональности очистки создания безрежимного диалогового окна, выделяемой для кучи.

Если вызвать удаление

Рекомендуется вызывать DestroyWindow для уничтожения объекта windows или метод API C++ или глобальное DestroyWindow.

Не вызывайте глобальное API DestroyWindow для уничтожения дочернее окно MDI.Необходимо использовать виртуальный метод CWnd::DestroyWindow.

Для объектов окна C++, которые не выполняют автоматическ-очистку, с помощью оператора delete может вызвать утечку памяти при попытке вызвать DestroyWindow в деструкторе CWnd::~CWnd если VTBL не указывает на правильно производному классу.Это происходит потому, что система не может найти соответствующее уничтожает вызываемый метод.Использование DestroyWindow вместо delete избежать этих проблем.Поскольку это может быть заметно ошибкой при компилировании в режиме отладки создаст следующее предупреждение, если в риск.

Warning: calling DestroyWindow in CWnd::~CWnd
   OnDestroy or PostNcDestroy in derived class will not be called

В случае объектов окон C++, которые выполняют автоматическ-очистку, необходимо вызвать DestroyWindow.При использовании оператора delete напрямую, то механизм распределения памяти MFC диагностический, уведомляющее о выпуске память 2 времени.2 Вхождения первого явный вызов и косвенный вызов delete this в реализации автоматическ-очистки PostNcDestroy.

После вызова DestroyWindow в объекте non-автоматическ-очистки объект C++, однако по-прежнему будет вокруг m_hWnd будет равно null.После вызова DestroyWindow в объекте автоматическ-очистки, будет пойден объект C++, освобожено оператора delete C++ в реализации автоматическ-очистки PostNcDestroy.

См. также

Другие ресурсы

Технические замечания по номеру

Технические замечания по категориям