Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 2004.05.02;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.03 c
14-1081426665
Nikolay M.
2004-04-08 16:17
2004.05.02
На какого героя советских мультиков вы больше всего похожи?


6-1079023940
SAG
2004-03-11 19:52
2004.05.02
Подтормаживание в TCPClient


4-1078573727
Igor5
2004-03-06 14:48
2004.05.02
Как получить список всех окон Windows (включая все дочерние)


14-1081172092
geg
2004-04-05 17:34
2004.05.02
Как определить чего ты стоишь как программист.


3-1081167723
Ivan
2004-04-05 16:22
2004.05.02
Информация в PageFooter





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский