TN017: Уничтожение объектов Window

В настоящей записке описывается использование функции-члена CWnd::PostNcDestroy . Используйте эту функцию, если вы хотите сделать заказной распределения CWnd-производные объекты.

Эта записка также объясняет некоторые из причин для кардинальное правило:

Чтобы уничтожить объект C++ Windows, используйте DestroyWindow не «удалить».

Это имеет важное значение. Если вы следите за следующие рекомендации, вы будете иметь некоторые проблемы очистки (например, забыв удалить/освободить память C++, забывая о том освободить системные ресурсы как HWNDs или освобождение объектов слишком много раз).

Проблема

Windows объекты (объекты классов, производных от CWnd) представляют собой объект C++ (выделены в куче приложения) и HWND (выделены в системных ресурсов диспетчером окон). Поскольку существует несколько способов уничтожить объект window, мы должны обеспечить набор правил, которые мешают системных ресурсов или утечек памяти приложения и это помешало объектов и дескрипторы Windows уничтожается более одного раза.

Это больше, чем проблема управления памяти. Присутствие в окне Windows имеет влияние интерфейса пользователя: окно на экране; После того, как он уничтожил существует также влияние на системные ресурсы. Утечка памяти в адресном пространстве приложения в C++ не так плохо, как утечка ресурсов системы.

Уничтожение Windows

Два способа разрешенных для уничтожения объекта Windows:

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

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

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

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

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

Эти классы, которые призваны быть сами по себе в куче переопределить функцию-член PostNcDestroy для выполнения "Удалить этот". Это заявление будет освободить связанную с объектом C++ память C++. Несмотря на то, что по умолчанию CWnd деструктор вызывает DestroyWindow если m_hWnd не NULL, это не приведет к бесконечной рекурсии так как дескриптор будет отдельностоящий и NULL в ходе этапа очистки.

Примечаниеnbsp;CWnd::Post&NcDestroy обычно вызывается после Windows WM_NCDESTROY сообщение обрабатывается, как часть окна уничтожения, и больше не прилагается HWND и объект window C++. CWnd::PostNcDestroy также будет вызываться в осуществлении большинства создать звонков, если сбой (см. ниже для автоматической очистки правил).

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

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

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

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

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

Когда для вызова «delete»

Для уничтожения объекта Windows рекомендуется называть DestroyWindow, либо функцию-член C++ или глобальной :: DestroyWindow API.

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

Для объектов C++ окна, которые не выполняют Автоочистка, использование DestroyWindow вместо удаления позволяет избежать проблем, имеющих для вызова DestroyWindow в CWnd:: ~ CWnd деструктор, где правильно производного класса не указывает VTBL. Это может привести к тонким ошибкам поэтому диагностика (Отладка) версии MFC предупредит вас с

Внимание: вызов DestroyWindow в CWnd:: ~ CWnd
 nbsp; OnDestroy или Post&NcDestroy в производном классе не будет вызвана

В случае объектов C++ Windows, которые выполняют Автоочистка, необходимо вызвать DestroyWindow. Если вы используете оператор, удалять напрямую, MFC распределителя памяти будет предупреждать вас о освобождая памяти дважды (первый звонок для удаления ), так и непрямой вызовУдалить этот"в осуществлении Автоочистка PostNcDestroy.

После вызова DestroyWindow для автоматической очистки объекта, объект C++ будет по-прежнему вокруг, но m_hWnd будет иметь значение NULL. После вызова DestroyWindow в Автоочистка объекте, объект C++ будет пошли, освободившись от оператора delete C++ в осуществлении Автоочистка PostNcDestroy..

Технические примечания по номеру |nbsp; Технические примечания по категориям

Index