Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Как обработать выключение компьютера?


Автор: E_v_g 24.1.2008, 11:12
При выключении компьютера завершаются все программы, а моя программа становится активной и комп не вырубается. При закрытии программы пользователем или при завершении работы ОС она должна сохранить настройки. Как это корректно реализовать?
Код

    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    { Private declarations }
    procedure WMQueryEndSession(var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;
    procedure WMEndSession(var Message: TWMEndSession); message WM_ENDSESSION;

Код

// вызывается при закрытии формы пользователем и при завершении Windows
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  SaveSettings;
  CanClose := true; // true - значит, можно закрыть
end;

procedure TForm1.WMQueryEndSession(var Message: TWMQueryEndSession);
begin
  inherited;
  Message.Result := 1; // если <> 0, то Windows можно завершить
end;

procedure TForm1.WMEndSession(var Message: TWMEndSession);
begin
  inherited;
  Message.Result := 1; // если <> 0, то Windows можно завершить
end;

Автор: MetalFan 24.1.2008, 12:18
настройки чтоли долго сохраняются?

Автор: E_v_g 25.1.2008, 11:29
Неа, быстро сохраняются. Короче, я ее победил - поставил Halt в каждом обработчике и все заработало как надо. Вроде бы...  smile 

Автор: MetalFan 25.1.2008, 14:05
сохраняй настройки в OnDestroy главной формы

Автор: E_v_g 26.1.2008, 05:52
Пробовал - при первой попытке выйти из Windows программа гаснет, Windows не завершается, требуется вторая попытка.

Автор: MetalFan 26.1.2008, 09:56
ерунда какаято.
что происходит во время сохранения опций?

Автор: E_v_g 28.1.2008, 06:02
Вот сохранение:
Код

procedure TForm1.SaveSettings;
var
  i : integer;
begin
  Memo2.Clear;
  Memo1.Clear;
  Memo3.Clear;
  Memo5.Clear;
  if CheckBox6.Checked then // если галочка на "сохранять", то
    begin
      // сохранить все данные формы
      WriteComponentResFile(fil, Self);
      Memo1.Clear;
      Memo1.Lines.Add('');
      // занести в Memo1 строки, отмеченные в трех CheckListBox-ах 
      for i := 0 to CheckListBox1.Items.Count - 1 do
        if CheckListBox1.Checked[i] then
          Memo1.Lines.Strings[0] := Memo1.Lines.Strings[0] + '1'
        else
          Memo1.Lines.Strings[0] := Memo1.Lines.Strings[0] + '0';
      Memo1.Lines.Add('');
      for i := 0 to CheckListBox2.Items.Count - 1 do
        if CheckListBox2.Checked[i] then
          Memo1.Lines.Strings[1] := Memo1.Lines.Strings[1] + '1'
        else
          Memo1.Lines.Strings[1] := Memo1.Lines.Strings[1] + '0';
      Memo1.Lines.Add('');
      for i := 0 to CheckListBox3.Items.Count - 1 do
        if CheckListBox3.Checked[i] then
          Memo1.Lines.Strings[2] := Memo1.Lines.Strings[2] + '1'
        else
          Memo1.Lines.Strings[2] := Memo1.Lines.Strings[2] + '0';
      Memo1.Lines.SaveToFile(fil1);
    end
end;

Кроме того, на форме есть WebBrowser и штук 5 Timer-ов, может, в них дело?

Автор: MetalFan 28.1.2008, 10:39
Цитата(E_v_g @  28.1.2008,  06:02 Найти цитируемый пост)
Вот сохранение:

корявенько, но вроде без криминала...

Цитата(E_v_g @  28.1.2008,  06:02 Найти цитируемый пост)
Кроме того, на форме есть WebBrowser и штук 5 Timer-ов, может, в них дело? 

таймеры... может их вырубить стоит в CloseQuery?

Автор: EvilsInterrupt 30.1.2008, 19:23
MetalFan,  не может, а нужно!

Автор: E_v_g 31.1.2008, 05:46
Убрал все это:
Код

 procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
 procedure WMQueryEndSession(var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;
 procedure WMEndSession(var Message: TWMEndSession); message WM_ENDSESSION;

Переписал завершение в OnDestroy:
Код

procedure TForm1.FormDestroy(Sender: TObject);
var
  i : integer;
begin
  Memo2.Clear;
  Memo1.Clear;
  Memo3.Clear;
  Memo5.Clear;
  Timer1.Free;
  Timer2.Free;
  Timer3.Free;
//  Timer4.Enabled := false;
  if CheckBox6.Checked then
    begin
      WriteComponentResFile(fil, Self);
      ............................
      Memo1.Lines.SaveToFile(fil1);
    end;
  inherited
end;


Теперь при завершении винды программа не гаснет, винда, соответственно, не завершается. Плюс к тому же не сохраняются настройки, то есть событие OnDestoy не происходит. Хотя при ручном закрытии формы сохранение работает.

Таймеры все убил smile

Автор: E_v_g 31.1.2008, 06:05
Ладно, мастера, спасибо, не ломайте голову, пока устраивает и так:
Цитата(E_v_g @  25.1.2008,  11:29 Найти цитируемый пост)
поставил Halt в каждом обработчике и все заработало как надо

(на этом же форуме натолкнулся на эту мысль)

Автор: simsmann 17.2.2008, 20:14
Вопрос поставлен давно, но до сих пор на него нет ответа!!!
Этот вопрос ставился на многих форумах, есть статьи но ничего не дает результата!!!
Вот некоторые ссылки

http://valler.narod.ru/master/ShutDown.html
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=57161
http://delphiworld.narod.ru/_app_.html

В том числе и на этом форуме вот тема поднималась в общих вопросах

http://forum.vingrad.ru/forum/topic-70589.html#st_0_view_0

Как правило трудности у тех программ которые помещают икону в систем трей.
Обработка WMQueryEndSession и WMEndSession ничего не дает, если даже программа на выходе ничего не сохраняет, все равно программа выгружается если обработать WMQueryEndSession и WMEndSession, а винда затормозилась и продолжает работать какбудто команды на выключение не было.

Кто решил данную проблема ОТКЛИКНИТЕСЬ!!! 

Автор: dumb 18.2.2008, 05:04
Цитата(simsmann @  17.2.2008,  20:14 Найти цитируемый пост)
Вопрос поставлен давно, но до сих пор на него нет ответа!!!
какой вопрос? куда поставлен?!

Цитата(simsmann @  17.2.2008,  20:14 Найти цитируемый пост)
а винда затормозилась и продолжает работать какбудто команды на выключение не было

в обработчике WM_QUERYENDSESSION вернуть TRUE, в обработчике WM_ENDSESSION вернуть 0, завершить выполнение программы.


Автор: simsmann 18.2.2008, 21:11
dump не надо грязи!   smile 

E v q четко поставил вопрос. Внимательно изучи вопрос потом давай советы.
E v q представил код 
Код

procedure TForm1.WMQueryEndSession(var Message: TWMQueryEndSession);
begin
  inherited;
  Message.Result := 1; // если <> 0, то Windows можно завершить
end;

procedure TForm1.WMEndSession(var Message: TWMEndSession);
begin
  inherited;
  Message.Result := 1; // если <> 0, то Windows можно завершить
end;


Message.Result := 1;  это тоже самое, что и TRUE

Цитата

в обработчике WM_QUERYENDSESSION вернуть TRUE, в обработчике WM_ENDSESSION вернуть 0, завершить выполнение программы.

Кстати 0 в WMEndSession запрещает завершение Виндов, точнее говорит о том, что прога не готова к завершению.
WMQueryEndSession отличается от WMEndSession только тем, что это первое и второе опевещение программ о завершении Виндов.
Цитата

какой вопрос? куда поставлен?!


А такой вопрос!!! Винда не завершается, как правило если вы помещаете икону программы в систем трей, там где часы и убираете отображение кнопки программы на панели задач. Причем не важно используете вы компоненты для этой цели (опробовал несколько) или своими ручками помещаете икону в систем трей.
И ставьте хоть сто раз в обработчиках WMEndSession и WMQueryEndSession :=TRUE или целое значение отличное от нуля, это значение тоже дает ОС сообщение, что программа готова к завершению Виндов (0 запрещает выгрузку ОС говоря, что окно не готово закрыться)

Самое интересное то, что при исследовании выяснилось, что ВИНДА второй раз(вначале опрашивается WMQueryEndSession, а потом если окна не готовы второй раз WMEndSession) не посылает сообщение. И проблема здесь наверно в том, что программа при помещении значка в систем трей сидит именно в процессах.
Закрытие программы  методом Close, Application.Terminate и выставление TRUE ничего не дает в обработчике WMQueryEndSession программа выгружается, а ВИНДА прекращает и WMEndSession не вызывается. Если все поставить в WMEndSession или туда и сюда тоже самое.
Прошерстил все форумы, данный ворос встречается часто, но ответа НЕТ!
Но слава БОГУ! и Винграду на котором всетаки нарисовался ответ. smile 
смотрите мой ответ по аналогичному вопросу, но в разделе общие вопросы.
Вот ссылка:
http://forum.vingrad.ru/forum/topic-70589/unread-1/anchor-entry1417174/15.html smile 



Автор: MetalFan 18.2.2008, 23:27
Цитата(simsmann @  18.2.2008,  21:11 Найти цитируемый пост)
Кстати 0 в WMEndSession запрещает завершение Виндов, точнее говорит о том, что прога не готова к завершению.

неправда!
Цитата(MSDN)
WM_ENDSESSION Message
...
Return Value
If an application processes this message, it should return zero.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)