Cамоучитель по Visual Studio.Net

       

Немодальный режим работы



Немодальный режим работы

Особенность работы с немодальным диалогом заключается в том, что надо затратить дополнительные усилия для корректного завершения его работы. Чтобы закрыть немодальный диалог, документация требует переопределить две виртуальные функции в классе диалога: обработчик закрытия диалога OnCancel и функцию PostNcDestroy. Существуют подробные рекомендации для завершения немодального диалога. Внутри вашей версии виртуальной функции OnCancel следует уничтожить окно диалога (DestroyWindow), а внутри другой виртуальной функции PostNcDestroy рекомендуется уничтожать объект диалогового класса (delete this;). С немодальным диалогом принято работать динамически (on heap frame), а не статически (on stack frame), как с модальным. Когда уничтожается окно Windows, то последним сообщением, которое ему посылается, является WM_NCDESTROY. Обработчик по умолчанию, то есть родительская версия cwnd: :OnNcDestroy, открепляет (detach) описатель окна HWND от объекта класса C++ и вызывает виртуальную функцию PostNcDestroy.

Некоторые классы переопределяют ее для того, чтобы произвести освобождение своих объектов в области heap (динамическая память). При неудаче в процессе создания окна происходит вызов функции cwnd::PostNcDestroy, которая ничего не делает, но дает возможность виртуальным двойникам корректно освободить динамическую память. Мы тоже будем работать с диалогом динамически (on heap frame). В классе документа будет храниться адрес объекта с Pol у Dig, который должен корректно следить за стадиями создания и уничтожения диалога. Я намеренно не переопределял PostNCDestroy, чтобы показать альтернативный способ, допустимый в частных случаях. Так как наш диалог завершается командой Close с идентификатором IDOK, то, введя обработчик этой команды, мы можем с помощью родительской версии уничтожить Windows-окно, а затем освободить память, занимаемую объектом собственного класса:

void CPolyDlg::OnClickedOk(void)

{

//=== Запоминаем факт отсутствия диалога в документе

m_pDoc->m_pPolyDlg = 0;

//====== Родительская версия вызовет DestroyWindow

CDialog::OnOK();


//====== Мы освобождаем память

delete this;

}

Вызов диалога производится в ответ на команду Edit > Poly Color, которая уже присутствует в меню IDR_DrawTYPE. Введите в класс CTreeDoc обработчик этой команды и наполните его кодами, как показано ниже:

void CTreeDoc::OnEditPolycolor(void)

{

//====== Если диалог отсутствует

if (!m_pPolyDlg)

{

//====== Создаем его в две ступени

m_pPolyDlg = new CPolyDlg(this);

m_pPolyDlg->Create(IDD_POLYCOLOR) ;

}

else

//===== Иначе делаем активным его окно

m_pPolyDlg->SetActiveWindow();

}

Здесь использован указатель на объект диалогового класса, который необходимо ввести в число public-данных класса CTreeDoc (CPolyDlg *m_pPolyDlg;) и обнулить в конструкторе документа (m_pPolyDlg = 0;). Сделайте это, а также введите в файл реализации класса CTreeDoc вспомогательную функцию UpdateDrawView:

void CTreeDoc::UpdateDrawView()

{

//====== Добываем адрес нужного представления

CDrawView *pView = dynamic_cast<CDrawView*>

(GetView(SCDrawView::classCDrawView));

//====== и просим его перерисоваться с учетом изменений

if (pView)

pView->Invalidate();

}



Содержание раздела