Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.02;
Скачать: CL | DM;

Вниз

Как закрыть программу, когда пользователь хочет перезагрузиться?   Найти похожие ветки 

 
Status   (2004-03-04 00:28) [0]

Моя программа запускается при загрузке операционной системы и невидима для пользователя.
Мне нужно ловить момент, когда пользователь хочет перезагрузиться или завершить работу windows, чтобы закрыть программу, иначе перезагрузки не происходит.

Ловлю сообщение WM_QUERYENDSESSION:
procedure WMQueryEndSession(var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;

далее в коде
PROCEDURE TForm1.WMQueryEndSession(var Message: TWMQueryEndSession);
var a:TCloseAction;
BEGIN
 FormClose(Form1, a);
 Message.Result := 1;
 form1.destroy;
END;

В файле проекта есть следующая строчка:
Application.ShowMainForm:=false;

Так вот, когда пытаюсь перезагрузиться то перезагрузки не происходит, но когда убираю из файла проекта эту строчку, то нормально windows перезагружается. Не пойму в чём дело.


 
Defunct ©   (2004-03-04 01:10) [1]

Делайте на уровне приложения а не главной формы:

 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject);
 protected
   Procedure IdleMessage(var MSG:tagMSG;var Handled:Boolean);
 End;

var
 Form1: TForm1;

implementation
{$R *.dfm}

Procedure TForm1.IdleMessage;
Begin
 With MSG.message=WM_QUERYENDSESSION Then
 Begin
   Handled := True;
   Destroy;
   Application.OnMessage := Nil;
   Application.Terminate;
 End;
End;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Application.OnMessage := IdleMessage;
End;


 
Defunct ©   (2004-03-04 01:24) [2]

ЗЫ, я думаю будет лучше проверять не WM_QUERYENDSESSION, а WM_ENDSESSION. ибо будет немного глупо выглядеть, когда ваша программа-агент завершится, а какая-то другая программа приостановит перезагрузку.


 
Defunct ©   (2004-03-04 01:54) [3]

Опечатка..

TForm1 = class(TForm)
  procedure FormCreate(Sender: TObject);
protected
  Procedure IdleMessage(var MSG:tagMSG;var Handled:Boolean);
End;

var
Form1: TForm1;

implementation
{$R *.dfm}

Procedure TForm1.IdleMessage;
Begin
If MSG.message=WM_ENDSESSION Then
Begin
  Handled := True;
  Destroy;
  Application.OnMessage := Nil;
  Application.Terminate;
End;
End;

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := IdleMessage;
End;


Код проверен, работает исправно с
Application.ShowMainForm := False;


 
Alexander666 ©   (2004-03-04 03:59) [4]


> Defunct ©   (04.03.04 01:10) [1]
> Делайте на уровне приложения а не главной формы:

ИМХО, как-то странно звучит.


 
Defunct ©   (2004-03-04 04:32) [5]

> ИМХО, как-то странно звучит.

В контексте сабжа это было про отлов сообщения WM_ENDSESSION и завершение работы посредством Close главной формы. Отлов сообщение WM_ENDSESSION и Application.Terminate это уже на уровне процесса. Не знаю как обрабатывается выход и отлов при Application.ShowMainForm = False, но на практике заметил, что с этим параметров сообщение окном формы не отлавливается, более того Close не срабатывает должным образом.


 
y-soft ©   (2004-03-04 07:55) [6]

Вообще-то нормально написанное приложение прекрасно завершается системой и без ловли WM_ENDSESSION и WM_QUERYENDSESSION

Чаще эти обработчики используются как раз для того, чтобы запретить Shutdown

Лишь иногда, когда необходимо корректно завершить длительный процесс или обеспечить завершение группы процессов в определенном порядке, в обработчике сначала приостанавливают перезагрузку, заканчивают долгую операцию, а потом приложение само повторно инициализирует Shutdown. Но способ этот достаточно капризный и не всегда приводит к ожидаемым результатам (например: Shutdown вызван ПО источника бесперебойного питания. В этом случае приостановка перезагрузки может привести к порче ОС и другим неприятностям, т.к. компьютер может вырубится  просто из-за падения питающего напряжения)


 
Status   (2004-03-04 19:20) [7]

To Defunct:
Что то по-моему ваш код вообще не работает, то есть сообщение не отлавливается.
Если допустим я хочу чтобы когда пользователь хочет перезагрузиться, чтоб перезагрузки не было и чтобы моя прога не закрылась я должен написать:

If MSG.message=WM_ENDSESSION Then
Begin
 Handled := false;
End;

Но никакой реакции - происходит перезагрузка.
И если вставляю какой нибудь код между
If MSG.message=WM_ENDSESSION Then
Begin
 *********
End;
То он тоже не выполняется.


 
Defunct ©   (2004-03-05 00:52) [8]

Специфика платформы..
В таком случае просто попробуйте в вашей, изначально приведенной процедуре, выполнить этот кусок кода:

Procedure TForm1.WMQueryEndSession(var Message: TWMQueryEndSession);
Begin
 Case Application.MessageBox("Закрыть программу?","exiting",MB_YESNO) Of
   IDYES:
     Begin
       Message.Result := 1;
       Destroy;
       Application.Terminate;
     End;
   IDNO:  Message.Result := 0;
 End;
End;


У меня работает.

Кстати, по поводу вашего второго вопроса

чтоб перезагрузки не было и чтобы моя прога не закрылась я должен написать:

If MSG.message=WM_ENDSESSION Then
Begin
Handled := false;
End;

"Handled" не имеет никагого отношения к Result сообщения, устанавливая в True, вы тем самым даете понять что сообщение обработано.
PS: из сабжевого вопроса, я так понял Вам было нужно чтобы программа завершалась, а не приостанавливала завершение сессии.


 
Defunct ©   (2004-03-05 01:03) [9]

ЗЫ, а вообще y-soft ©   (04.03.04 07:55) [6] прав.


 
Status   (2004-03-06 03:05) [10]

Понял в чём проблема!
В общем надо было мне, чтобы происходила нормальная перезагрузка компа, когда моя прога запущена. Но как оказалось, перезагрузка приостанавливается. Сообщение WM_ENDSESSION не ловится. А если убираю строчку Application.ShowMainForm:=false;
то всё нормально.
Самое интересное, что когда создаю новое чистое приложение, вставляю эту строчку и делаю обработку сообщения WM_ENDSESSION, то всё без проблем.
Так вот, как оказалось, проблема в компоненте TNMSmtp!!! (который я использую в своей программе).
Стоит убрать его и сообщение WM_ENDSESSION ловится отлично.
Вот так то.
По этому поводу вопрос: каким образом решить эту проблему. Я вижу я пути:
1). Создавать NMSmtp в процессе работы программы и после отсылки почты удалять и так каждый раз. Но может возникнуть ситуация, что пользователь хочет перезагрузиться, а NMSmtp существует, тогда облом.
2). Отсылать почту каким-ниубдь другим методом, только каким? Я не знаю.
3). Отлавливать сообщение WM_ENDSESSION каким-либо другим методом, ставить глобальный хук. Как это сделать?


 
Alexander666 ©   (2004-03-06 06:20) [11]

Агааа!!! Трояна пишем или червя?! :-)) Отсылай почту методами API, в Интернете в факах поройся... или, если уж это действительно, что компонент мешает перезагружаться (хотя я в этом сомневаюсь), то переделывай сам этот компонент. Ищи причину его упорства при перезагрузке в исходных кодах.


 
Status   (2004-03-06 14:14) [12]

Всё таки интересует вопрос, как можно поставить хук на WM_ENDSESSION


 
Status   (2004-03-06 15:07) [13]

Попробовал поставить хук на WH_GETMESSAGE:

GlobalData^.HookHandle_Getm:=SetWindowsHookEx(WH_GETMESSAGE, @GetmHook, HInstance, 0);

Function GetmHook(Code: Integer; ParamW: WPARAM; ParamL: LPARAM): LRESULT;stdcall;
Begin
 If Code<0 Then
 Begin
   Result := CallNextHookEx(GlobalData^.HookHandle_Getm, Code, ParamW, ParamL);
   Exit;
 End;
 if (Code=HC_ACTION) then
 begin
   with TMsg(Pointer(paraml)^) do
   if (message = WM_ENDSESSION) then
   begin
     SendMessage(GlobalData^.ProgHandle_Getm, WM_TESTMES, paramw, Code);
   end;
 end;
 Result := CallNextHookEx(GlobalData^.HookHandle_getm, Code, ParamW, ParamL);
End;

Не работает, но если делаю проверку message = WM_KEYDOWN то работает.
Может с помощью хука на WH_GETMESSAGE нельзя отловить сообщение о перезагрузке системы?



Страницы: 1 вся ветка

Текущий архив: 2004.05.02;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.024 c
11-1045034380
Un-man
2003-02-12 10:19
2004.05.02
OnIdle в KOL


1-1082202234
Mishenka
2004-04-17 15:43
2004.05.02
Не выводится TPrintDialog.


3-1081411563
Slider007
2004-04-08 12:06
2004.05.02
Имя запроса MSAccess в Delphi


14-1081541828
kaif
2004-04-10 00:17
2004.05.02
Еще раз о праве владения на квартиру


14-1081635133
Soft
2004-04-11 02:12
2004.05.02
Соционика или типизация человеческой личности.