Форум: "Основная";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];
ВнизЭтот таинственный MessageBox... Найти похожие ветки
← →
Bless © (2006-10-10 10:21) [0]Сперва приведу тестовый пример.
Итак, создаем новое приложение с двумя формами. На form1 бросаем кнопку и пишем обработчик OnClick:procedure TForm1.Button1Click(Sender: TObject);
begin
form2 := tform2.create(self);
end;
У form2 есть такие обработчики:procedure TForm2.FormCreate(Sender: TObject);
begin
try
raise Exception.Create("my exception");
except
PostMessage(handle, WM_CLOSE,0,0);
Windows.MessageBox(0, "11", "22", mb_ok); //!!!!!!!!!!!!!!!!!!!!!!!
end;{try}
end;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
action := caFree;
end;
Если поставить точку останова на выделенную строчку в TForm2.FormCreate и нажать f8, то меня заносит в обработчик TForm2.FormClose (!?!), после чего возвращает назад в TForm2.FormCreate (на последний end;). Почему это происходит?
← →
ors_archangel © (2006-10-10 10:34) [1]Думаю, появление MessageBox вызывает обработку сообщения WM_CLOSE (у него там модальный message loop, видимо) приложением, а так как мы трейсимся, то мы и трейсимся в WM_CLOSE-обработчик, но Делфи останавливается по Ф8 только на коде нашего проекта, поэтому мы попадаем, я так думаю, в FormClose. После присвоения в этом обработчике, сообщение WM_CLOSE мы больше не увидим (больше негде) и поэтому возвращаемся к коду FormCreate. Код FormCreate в блоке except по любому выполняется, даже если мы и присваиваем action = caFree, мы не убиваем этим форму (и тем более нить) сейчас же. Когда отлаживаешь multithread-проги, тоже весело бывает очень :)
← →
Плохиш © (2006-10-10 10:38) [2]
> Почему это происходит?
Потому что происходит обработка оереди сообщений.
← →
Bless © (2006-10-10 10:46) [3]
> ors_archangel © (10.10.06 10:34) [1]
Не совсем понимаю, что такое модальный message loop, но ты уверен, что он имеет какое-то отношение к Windows.MessageBox, к тому же с параметром hWnd (который Identifies the owner window) = 0?
То, что FormClose вызвался как результат обработки сообщения WM_CLOSE, это понятно.
Непонятно только, кто его сгенерировал.
Причем (тут я могу ошибаться, конечно), впечатление такое, что WM_CLOSE попало к Form2 не из очереди сообщений (такое впечатление сложилось потому, что в Application.ProcessMessages по F8 на выделенной строчке не попало, а ведь должно бы?), а через прямой вызов оконной процедуры (DispatchMessage?). Но кто этот вызов сделал, что-то не пойму.
← →
Bless © (2006-10-10 10:49) [4]
> Плохиш © (10.10.06 10:38) [2]
> Потому что происходит обработка оереди сообщений.
А как я в эту обработку тогда попал, не расскажешь?
← →
Bless © (2006-10-10 10:52) [5]Вдогонку [4]
Приложение-то однопоточное, я сейчас нахожусь в обработчике FormCreate. Каким образом меня вдруг закинуло в цикл обработки сообщений, а потом вернуло обратно?
← →
Игорь Шевченко © (2006-10-10 10:52) [6]Bless © (10.10.06 10:46) [3]
> Не совсем понимаю, что такое модальный message loop
Выборка из очереди потока сообщений, относящихся только к определенному окну. Поток-то один, в недрах MessageBox крутится цикл выборки сообщений, который больше никому не отдает управления.
← →
Elen © (2006-10-10 10:53) [7]
> Bless
Ну ты ж вызываеш эту обработку через PostMessage(handle, WM_CLOSE,0,0)?
Верно ведь? Хендл то формовский
← →
Игорь Шевченко © (2006-10-10 10:53) [8]Bless © (10.10.06 10:52) [5]
> Каким образом меня вдруг закинуло в цикл обработки сообщений,
> а потом вернуло обратно?
Цикл выборки сообщений вызвал оконную процедуру формы для обработки синхронного сообщения, например.
← →
Elen © (2006-10-10 10:59) [9]Поправочка - "вызываеш" надо читать "помешаеш в очередь сообщений"
← →
Bless © (2006-10-10 11:18) [10]> Игорь Шевченко © (10.10.06 10:53) [8]
> Цикл выборки сообщений вызвал оконную процедуру формы для
> обработки синхронного сообщения, например.
Не понял. Где я ошибаюсь?
Вся программа по сути - это цикл обработки сообщений. В данный момент я как раз обрабатываю одно из них, которое завело меня в конечном итоге вprocedure TForm2.FormCreate
. Когда я закончу, то попаду назад в цикл, который выберет следующее сообщение (которое вполне может оказаться WM_CLOSE, которое я туда поместил строчкойPostMessage(handle, WM_CLOSE,0,0);
) из очереди и обработает его.
На самом деле все происходит не совсем так?
← →
Bless © (2006-10-10 11:22) [11]Или Вы хотите сказать, что обработчик сообщения WM_CLOSE для окна был вызван изнутри цикла MessageBox-а?
← →
Elen © (2006-10-10 11:25) [12]
> Bless
Нет когда ты возвал PostMessage. Ты поставил WM_Close в очередь событий. Просто перед ним были tit сообщения, ожидающие своей обработки. А когда дело дошло до WM_Close то пошло в close. Замени MessageBox на любой другой оператор и будет практически та же реакция Имхо
← →
Bless © (2006-10-10 11:28) [13]
> Elen © (10.10.06 10:59) [9]
> Поправочка - "вызываеш" надо читать "помешаеш в очередь
> сообщений"
Вот именно. Не вызываю, а помещаю в очередь, в расчете на то, что оно будет обработано не раньше, чем произойдет очередная выборка очередного сообщения из очереди сообщений. То есть всяко после TForm2.FormCreate, а не посредине него.
← →
Bless © (2006-10-10 11:32) [14]
> Замени MessageBox на любой другой оператор и будет практически
> та же реакция
Заменил наform2 := nil;
. Реакция другая. Как и следовало ожидать, процедура TForm2.FormCreate отработала до конца и лишь затем был вызван TForm2.FormClose.
← →
han_malign © (2006-10-10 11:33) [15]MB_TASKMODAL
← →
Плохиш © (2006-10-10 11:34) [16]
> Bless © (10.10.06 11:22) [11]
Объясняю на пальцах. Вызвав MessageBox, который ждёт, как, надеюсь, известно, реакции пользователя, ты передал управление из своей программы системе, а та в свою очередь включила обработку сообщений, потому что другим способом реакцию пользователя как-то узнать труднова-то. Соответственно были обработаны все сообщения пришедшие приложению. Тот же самый эффект ты получишь просто вызвав Application.ProcessMessages.
← →
Elen © (2006-10-10 11:35) [17]
> Bless
Чего б не поставить PostMessage или Form2.close после всех нужных действий в Эксцепте?
← →
Bless © (2006-10-10 11:40) [18]
> Плохиш © (10.10.06 11:34) [16]
Т.е. я в [11] все верно написал?
Но меня как-то смущает:
> Игорь Шевченко © (10.10.06 10:52) [6]
> Bless © (10.10.06 10:46) [3]
> > Не совсем понимаю, что такое модальный message loop
> Выборка из очереди потока сообщений, относящихся только
> к определенному окну. Поток-то один, в недрах MessageBox
> крутится цикл выборки сообщений, который больше никому не
> отдает управления.
Так внутренний цикл MessageBox-а обрабатывает только сообщения, относящиеся к окну MessageBox-а или все-таки все сообщения? Где об этом можно четко прочитать?
← →
Плохиш © (2006-10-10 11:44) [19]
> Так внутренний цикл MessageBox-а обрабатывает только сообщения,
> относящиеся к окну MessageBox-а или все-таки все сообщения?
MessageBox выполняется в основном потоке программы, а сообщения обрабатываются по потокам, а не по окнам.
← →
han_malign © (2006-10-10 12:02) [20]
> Где об этом можно четко прочитать?
Help->MessageBox->Flags: MB_APPLMODAL/MB_SYSTEMMODAL/MB_TASKMODAL
модальные окна не блокируют(по умолчанию) очередь сообщений для других окон,
тут кто-то уже ставил MB на таймер и был (не)приятно удивлен...
Application.ProcessMessages
GetMessage(MSG, 0,...)
DispatchMessage
<MB.ProcessMessages>
GetMessage((MSG, зависит от флагов,...)
DispatchMessage
loop
loop
← →
Bless © (2006-10-10 12:13) [21]
> Elen © (10.10.06 11:35) [17]
> Чего б не поставить PostMessage или Form2.close после всех
> нужных действий в Эксцепте?
В данном примере это можно сделать. Но к сути вопроса это отношения не имеет, а пример создан лишь для иллюстрации вопроса.
← →
default © (2006-10-10 12:31) [22]Bless © (10.10.06 12:13) [21]
представь, что вместо вызова MessageBox ты создаёшь окно для диалога с пользователем(через CreateWindow(Ex)) и запускаешь цикл выборки сообщений отбирая в нём сообщения относящиеся только к созданному окну - это получится некое подобие модального вызова MessageBox
а вот если ты принимаешь на обработку сообщения относящиеся ко всем окнам, то тогда это будет некое подобие немодального вызова MessageBox
у тебя MessageBox вызывается немодально, поэтому ведётся обработка сообщений для всех окон и потому WM_CLOSE главного окна и обрабатывается
← →
default © (2006-10-10 12:44) [23]
> отбирая в нём сообщения относящиеся только к созданному
> окну - это получится некое подобие модального вызова MessageBox
это лишь некое подобие
на самом деле модальный показ MessageBox блокирует не все сообщения для других окон
в чём легко убедиться, например, вызвав модально MessageBox на главном окне, потом открыть другую программу и снова исходную программу - и увидим, что главное окно перерисовалось - значит сообщения по отрисовке главного окна "пропускаются" циклом выборки сообщений генерируемым модальным вызовом MessageBox
а вот сообщения по закрытию окна в модальном вызове MessageBox не пропускаются
← →
default © (2006-10-10 12:49) [24]
> "пропускаются" циклом
пропускаются на обработку всмысле:)всмысле обрабатываются:)
← →
Bless © (2006-10-10 17:13) [25]
> han_malign © (10.10.06 12:02) [20]
> > Где об этом можно четко прочитать?
>
> Help->MessageBox->Flags: MB_APPLMODAL/MB_SYSTEMMODAL/MB_TASKMODAL
Что-то я здесь не нашел информации о том, какие сообщения обрабатываются внутри MessageBox.
> default © (10.10.06 12:31) [22]
> у тебя MessageBox вызывается немодально, поэтому ведётся
> обработка сообщений для всех окон и потому WM_CLOSE главного
> окна и обрабатывается
Даже если я вызову его немодально, WM_CLOSE все-равно обработается.
Видимо, в [11] я угадал правильно (точнее не угадал, а переспросил сказанное в [6]). Внутри MessageBox, похоже, действительно организован свой собственный цикл выборки сообщений, который и вызвал обработчик WM_CLOSE.
← →
Bless © (2006-10-10 17:14) [26]Да, чуть не забыл.
Спасибо :)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.055 c