Форум: "WinAPI";
Текущий архив: 2003.06.02;
Скачать: [xml.tar.bz2];
ВнизWM_ENDSESSION Найти похожие ветки
← →
nikkie (2003-04-02 23:39) [0]Пишу программу с использованием WinAPI. В общих чертах, выглядит она так:
<код инициализации>
hwnd = CreateDialog(...)
<цикл выборки сообщений while(GetMessage)>
DestroyWindow(hwnd)
<освобождение ресурсов, захваченных при инициализации>
Какая-то инициализация находится в обработчике WM_INITDIALOG, соответствующее освобождение + сохранение текущего состояния в обработчике WM_DESTROY. Программа висит в трее, поэтому PostQuitMessage вызывается по пункту меню, а не в ответ на WM_CLOSE.
Выяснилось, что когда делается Log off <user>, программа не завершается корректным образом. Программа из цикла выборки сообщений не выходит, окно не разрушается, состояние не сохраняется, код освобождения ресурсов не вызывается. (Не знаю даже как система завершает программу - неужели через TerminateProcess?)
Насколько я понимаю, если делать PostQuitMessage в ответ на WM_ENDSESSION, то программа может просто не успеть завершиться... Конечно, можно можно сделать DestroyWindow в ответ на WM_ENDSESSION, но все равно код после цикла выборки сообщений вызываться не будет. Вроде никаких ресурсов, которые остались бы занятыми после смерти процесса я не занимаю, но если бы занимал?
Такое ощущение, что сама структура программы должна быть пересмотрена, например, при получении WM_ENDSESSION цикл должен прерываться. Только вопрос - почему ни в одном примере от MS я этого не видел? Другой вариант - освобождение ресурсов должно быть вынесено в отдельную cleanup-процедуру, которая будет вызывается после выхода из цикла выборки сообщений и из обработчика WM_ENDSESSION. Но поскольку я не уверен каким образом система завершает программу, то я не могу быть уверенным, что на другой ОС я не получу WM_QUIT, не выйду из цикла и cleanup-процедура не будет вызвана повторно...
Поделитесь, пожалуйста, соображениями на эту тему.
← →
Юрий Зотов (2003-04-03 01:18) [1]А почему WM_ENDSESSION, а не WM_QUERYENDSESSION? До завершения кода освобождения ресурсов можно возвращать False (без выхода из цикла), а чтобы юзер не дергался, выдать ему диалог в стиле TheBat!
← →
Suntechnic (2003-04-03 06:38) [2]>Юрий Зотов ©
На WM_QUERYENDSESSION вы всего лишь должны подтвердить системе, что вы согласны с тем, что Windows сейчас выгрузится. Если в ответ на это сообщение вернуть false то выгрузки попросту не произойдёт... более того... если особождать все ресурсы на WM_QUERYENDSESSION, то нет никакой гарантии, что кто-то не вернёт false на это сообщение и выгрузка Windows на этом закончится, а наше приложение останется "в дураках" (ресурсы освобождены, но систему не выгрузили).
>nikkie ©
После WM_ENDSESSION программа по крайней мере точно не получает WM_CLOSE и WM_DESTROY сообшения. Об этом сказано в статье Q77135. ИХМО освобождение ресурсов надо проводить в cleanup процедуре в ответ на WM_DESTROY сообщение и на WM_ENDSESSION(если wParam равно TRUE) и это будет гарантией того, что cleanup не будет вызвана дважды. На счёт того, что программа не успеет завершиться беспокоиться сильно тоже не стоит. Пока мы не вернулись из этого сообщения система не выгрузится. Так по крайней мере утверждает MSDN:
the session can end any time after all applications have returned from processing this message.
Но на самом деле мы все, наверное, были очевидцами того, как при выгрузке Windows заявляет о том, что такое-то приложение не отвечает на запросы и спрашивает нас что с ним делать дальше. Это, скорее всего, приложение долго не возвращается из обработчика WM_ENDSESSION и OS считает его "отвисшим". Но в любом случае нас запрашивают о дальнейших действиях.
← →
nikkie (2003-04-03 09:01) [3]>Юрий Зотов
Почему не WM_QUERYENDSESSION - Suntechnic хорошо ответил. Я с ним согласен.
>Suntechnic
Видимо надо делать отдельную cleanup-процедуру и вызывать ее по WM_ENDSESSION. Как-то нарушается простая линейная логика программы. Странно, почему windows не присылает просто WM_QUIT.
WM_CLOSE и WM_DESTROY совершенно не беспокоят. Если окно разрушено, то в WndProc уже ничего не попадет. Беспокоит WM_QUIT и слова
the session can end any time after all applications have returned from processing this message.
Вроде бы в моем случае ничего плохого не случится (по причине того что PostQuitMessage вызывается только по пункту меню), но если сделать так, как предлагается в MSDN
An application usually calls PostQuitMessage in response to the WM_DESTROY message, as shown in the following example.
case WM_DESTROY:
// Perform cleanup tasks.
PostQuitMessage(0);
break;
а по WM_ENDSESSION делать DestroyWindow и cleanup, то ведь WM_QUIT может успеть дойти и cleanup вызовется второй раз. Видимо надо ставить подпорку на эту тему.
← →
URSUS (2003-04-03 17:23) [4]Такая фигня происходит при использовании компонент NetMasters или чего-то вроде того (TNMHTTP например), я тоже долго трахался с этим - ну никак не завершается сеанс винды и все тут; пришлось поменять компонент на Indy.
← →
Puke Zero (2003-04-05 13:08) [5]Подскажите, что означает, если WM_QUERYENDSESSION ловится такой процедурой:
type
TForm1 = class(TForm)
private
procedure WMQueryEndSession(var Message: TMessage); message WM_QUERYENDSESSION;
....
но не ловится в WndProc. Вообще, какая между этими способами разница?
в .dpr:
Application.OnMessage:=Form1.WMProc;
procedure TForm1.WMProc(var Message: TMsg ;var Handled: Boolean);
begin
case Message.message of
WM_QUERYENDSESSION: begin
...
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2003.06.02;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.008 c