Что за фигня с WM_CLOSE?
От: SWW Россия  
Дата: 21.06.04 08:18
Оценка:
Имеется WTL-ное MDI-приложение. Когда оно стало довольно большим, обнаружилась неприятность: при закрытии чайлдового окна программа в дебуге вылетает во время прохождения сообщения WM_CLOSE. Даже если чайлд не обрабатывает WM_CLOSE.

atlwin.h
template <class TBase, class TWinTraits>
LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    <...>
    BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
    // restore saved value for the current message
    ATLASSERT(pThis->m_pCurrentMsg == &msg);
    pThis->m_pCurrentMsg = pOldMsg;
    // do the default processing if message was not handled
    if(!bRet)
    {
        if(uMsg != WM_NCDESTROY)
            lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
                        ^^^^^^^здесь чайлдовое окно уничножается
        else
        {
            // unsubclass, if needed
            LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
            lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
            if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
                ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
            // mark window as destryed
            pThis->m_dwState |= WINSTATE_DESTROYED;
        }
    }
    if((pThis->m_dwState & WINSTATE_DESTROYED) && pThis->m_pCurrentMsg == NULL)
         ^^^^^^^а здесь к нему происходит обращение
    {
    ...

Рассматривая работу сампла MDIDocVw выяснилось, что там тоже происходит обращение к уже уничноженному окну, но там pThis указывает на валидную память, поэтому ничего страшного не происходит. В моем же случае pThis начинает указывать на недействительную память.
Кто-нибудь сталкивался с этим? Это что: глюк WTL или я что-то не так делаю?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.