PDA

Просмотр полной версии : MessageBox в ~CMainFrame



Sera
02.09.2005, 13:33
Hi, all!

Создаю стандартный MFC SDI-проект визардом.
Получаю класс CMainFrame.

В деструктор добавляю строку:



CMainFrame::~CMainFrame()
{
::MessageBox(NULL, _T("Hi"), _T("Hi"), 0);
}

Никакой MessageBox не появляется.
Кто может мне это объяснить?

Спасибо!

ssDev
02.09.2005, 14:40
Деструктор MainFrame вызывается при завершении основного потока приложения а MessageBox(NULL, не блокирующий. В любом случае деструктор вызывается на PostNCDestroy так что если MessageBox и создается то не надолго (врятли даже отрисоватся успеет).

Sera
02.09.2005, 17:54
Почему он "не блокирующий"?
Если в где-нибудь добавить такой MessageBox, то программа будет ждать, пока не нажмешь ok.

Eugie
03.09.2005, 13:27
MessageBox конечно блокирующий (modal), но деструктор ~CMainFrame() вызывается, когда очередь сообщений потока уже разрушена => процедура создания и отображения (диалогового) окна штатно не срабатывает (не вызываются обработчики сообщений).

ssDev
05.09.2005, 06:40
По поводу блокировки,.
Да действительно MessageBox- modal, но MessageBox(NULL, имеет парентом десктоп. Поэтому если после появления такого MessageBox сново передать фокус приложению то само приложение будет обрабатывать события.
Простой пример

void CMainFrame::OnEditCopy()
{
::MessageBox(NULL, _T("Hi"), _T("Hi"), 0);
::MessageBox(NULL, _T("Hi"), _T("Hi"), 0);
::MessageBox(NULL, _T("Hi"), _T("Hi"), 0);
}

Выполнение OnEditCopy блокируется при вызове MessageBox но эту функцию можно вызывать много раз.

Eugie
06.09.2005, 14:55
Ну, если знать, как все это реализовано, то ничего удивительного тут нет. Модальный диалог при создании блокирует (disable) своего хозяина (owner). Нет хозяина - нечего блокировать.

Sera
08.09.2005, 11:30
Euqie, Что ты подразумеваешь под owner-ом MessageBox-а ?
Окно с хендлом hwnd, которое передается первым параметром?

Я думаю, что функция "MessageBox" синхронная (не знаю, имел ли в виду ssDev под словом "блокирующая" то же самое).
Синхронная -- значит, не передает управление следующей инструкции, пока не завершит свое выполнение.

Так что я не соглашусь с последним выводом. К примеру, возьмем консольное приложение:
int main()
{
::MessageBox(NULL, _T("Hi"), _T("Hi"), 0);
return 0;
}
Кто тут это "блокируемый" хозяин(owner) ? И почему его нет в деструкторе CMainFrame-а?

Eugie
08.09.2005, 13:41
Euqie, Что ты подразумеваешь под owner-ом MessageBox-а ?
Окно с хендлом hwnd, которое передается первым параметром?

Именно


Я думаю, что функция "MessageBox" синхронная (не знаю, имел ли в виду ssDev под словом "блокирующая" то же самое).
Синхронная -- значит, не передает управление следующей инструкции, пока не завершит свое выполнение.

В этом смысле - да. Но не все так просто. MessageBox, как и любой модальный диалог Windows, при создании запускает собственный цикл сообщений (message pump) и не выходит из него, пока диалог не будет закрыт (т.е. является синхронной функций в твоем понимании). Это не все. Специфика модальности ввода, как она реализована в Windows, предусматривает еще блокировку (disabling) окна-владельца. Но если нет владельца (соотв.параметр NULL), то и блокировки нет. Выглядит это в типичном GUI приложении как возможность переключиться на любое другое незаблокированное окно приложения - например, вызвать меню для главного окна. Вот что имел в виду ssDev. Все это время обрабатывать сообщения будет не главный цикл приложения, а цикл диалогового окна. В этом смысле мы из диалога не выходим, пока он не будет закрыт. Для твоего примера с консольным приложением эффект блокировки достигается именно поэтому: других окон нет и переключиться некуда, а поток управления, действительно, стоит в MessageBox до его закрытия.

Насчет ситуации с деструктором. Я не знаком с исходниками Windows ;) но уверен, что системные функции типа GetMessage/PeekMessage, которые используются при организации цикла сообщений, проверяют наличие валидной очереди сообщений, а она к моменту вызова деструктора главного окна приложения уже скорее всего разрушена/невалидна. Если вызывать MessageBox в деструкторе любого подчиненного окна, думаю, никаких проблем не будет .

Sera
08.09.2005, 16:55
Да, в этот раз соглашусь. Думаю, дело в отсутствии "живой" очереди сообщений.

В WTL::~CMainFrame у меня был MessageBox (в дебаговых целях), который отлично работал.
В MFC::~CMainFrame MessageBox не поднимается.

Вот так-то вот! Спасибо всем за совместное разгребание проблемы :)