Форум OlegON > Компьютеры и Программное обеспечение > Операционные системы и программное обеспечение > Программирование

Программа в трее и перезагрузка/выключение компютера : Программирование

29.03.2024 15:47


17.04.2009 12:51
Mihon
 
Ура!
Я нашел решение одной наболевшей проблемы...
Вобщем, когда на Delphi пишешь программу, которая должна сворачиваться в трэй, приходится кодить:
Код:
TForm1 = class(TForm)
...
  private
    { Private declarations }
    procedure TrayDefaultHandler (var Message:TMessage);
  public
    { Public declarations }
    data:tnotifyicondata;
...   
  end;
...
var
  Form1: TForm1;
...
const
  WM_TRAYICON = WM_USER+1;
  ID_TRAYICON = 1;
...
implementation
...
procedure TForm1.FormCreate(Sender: TObject);
var
  H:THandle;
begin
  H:=AllocateHWnd(self.TrayDefaultHandler);
  Data.cbSize:=SizeOf(TNotifyIconData);
  Data.Wnd:=H;
  Data.uCallbackMessage:=WM_TRAYICON;
  Data.uFlags:=NIF_ICON or NIF_TIP or NIF_MESSAGE;
  Data.hIcon:=Application.Icon.Handle;
  StrPCopy (data.szTip,Application.Title);
  Shell_NotifyIcon (NIM_ADD,@data);
...
end;
...
procedure TForm1.TrayDefaultHandler (var Message:TMessage);
var
  pt:tpoint;
begin
  if Message.Msg=WM_TRAYICON then
  begin
    if Message.LParam=WM_RBUTTONDOWN then
    begin
      getcursorpos(pt);
      FORM1.PopupMenu1.Popup(pt.X,pt.Y); //всплывающее меню
    end;
    if Message.LParam=WM_LBUTTONDOWN then
      if iswindowvisible(Application.Handle) and iswindowvisible(Handle) then
//это чтоб при щелчке левой кнопкой сворачивалось-разворачивалось
        begin
          ShowWindow(Handle, SW_HIDE);
          ShowWindow(Application.Handle,SW_HIDE);
        end else
        begin
          ShowWindow(Handle, SW_NORMAL);
          ShowWindow(Application.Handle,SW_NORMAL);
        end;
  end;
end;
...
Однако, если попробовать перезагрузить комп или выключить (через пуск) то программа остается висеть в памяти. И комп фиг перезагрузишь, пока через диспетчер задач прогу не вырубишь (или просто не закроешь).
Облазил множество форумов, нашел:
Код:
TForm1 = class(TForm)
...
  private
    { Private declarations }
    procedure WMQueryEndSession(var Msg : TWMQueryEndSession); message WM_QUERYENDSESSION;
...
implementation
...
procedure TForm1.WMQueryEndSession(var Msg : TWMQueryEndSession);
begin
  inherited;
//делаем все что нужно перед закрытием
  Msg.Result:=1;
  close; //закрываем
end;
НО, ситуация получится следующая:
В первый раз, когда вы щелкните по перезагрузке или выключению, закроются некоторые приложения и ваша висящая в трее программа.
А комп не перезагрузится/не выключится.
Сделает это он только со второго раза.
фуф, наконец-то нашел решение:
в процедуру TrayDefaultHandler надо добавить:
Код:
if message.Msg=WM_QUERYENDSESSION then
  begin
    message.Result:=1;
  end;
В итоге, получаем:
Код:
TForm1 = class(TForm)
...
  private
    { Private declarations }
    procedure TrayDefaultHandler (var Message:TMessage);
    procedure WMQueryEndSession(var Msg : TWMQueryEndSession); message WM_QUERYENDSESSION;
  public
    { Public declarations }
    data:tnotifyicondata;
...   
  end;
...
var
  Form1: TForm1;
...
const
  WM_TRAYICON = WM_USER+1;
  ID_TRAYICON = 1;
...
implementation
...
procedure TForm1.WMQueryEndSession(var Msg : TWMQueryEndSession);
begin
  inherited;
//делаем все что нужно перед закрытием
  Msg.Result:=1;
  close; //закрываем
end;
...
procedure TForm1.FormCreate(Sender: TObject);
var
  H:THandle;
begin
  H:=AllocateHWnd(self.TrayDefaultHandler);
  Data.cbSize:=SizeOf(TNotifyIconData);
  Data.Wnd:=H;
  Data.uCallbackMessage:=WM_TRAYICON;
  Data.uFlags:=NIF_ICON or NIF_TIP or NIF_MESSAGE;
  Data.hIcon:=Application.Icon.Handle;
  StrPCopy (data.szTip,Application.Title);
  Shell_NotifyIcon (NIM_ADD,@data);
...
end;
...
procedure TForm1.TrayDefaultHandler (var Message:TMessage);
var
  pt:tpoint;
begin
  if Message.Msg=WM_TRAYICON then
  begin
    if Message.LParam=WM_RBUTTONDOWN then
    begin
      getcursorpos(pt);
      FORM1.PopupMenu1.Popup(pt.X,pt.Y); //всплывающее меню
    end;
    if Message.LParam=WM_LBUTTONDOWN then
      if iswindowvisible(Application.Handle) and iswindowvisible(Handle) then
//это чтоб при щелчке левой кнопкой сворачивалось-разворачивалось
        begin
          ShowWindow(Handle, SW_HIDE);
          ShowWindow(Application.Handle,SW_HIDE);
        end else
        begin
          ShowWindow(Handle, SW_NORMAL);
          ShowWindow(Application.Handle,SW_NORMAL);
        end;
  end;
  if message.Msg=WM_QUERYENDSESSION then
  begin
    message.Result:=1;
  end;
end;
...
И радуемся жизни!
17.04.2009 13:30
twix
 
а почему бы не использовать RxLib, чтобы не приходилось изобретать велосипед?
17.04.2009 13:54
Mihon
 
Цитата:
twix а почему бы не использовать RxLib, чтобы не приходилось изобретать велосипед?
Ну используй.

Я RxLib тоже использую. Иногда.
А иногда можно и покодить немного. Не правда ли?
17.04.2009 15:01
NewBot
 
*107 я валяюсь с кода такого...
17.04.2009 15:10
Mihon
 
Цитата:
NewBot *107 я валяюсь с кода такого...
Ну я однозначно не монстр программирования. Но код рабочий.
Ну а вообще с кода валяться - это не здорОво.

Напиши код лучше. Или правильней. Что уж там тебя улыбнуло не знаю.
17.04.2009 15:51
twix
 
Цитата:
Mihon Ну используй.
я и использую, када надо (;

Цитата:
А иногда можно и покодить немного. Не правда ли?
можно... только вот, имо, кодить лучше что-то новое, а не изобретать велосипед, как я уже говорил.

ЗЫЖ без обид (8
17.04.2009 19:21
OlegON
 
Дело не в велосипеде. В RxLib все уже готовое, но увы, с ошибками. Я даже как-то постил баги где-то. А то, что написано самим собой значительно более проверено и легче правится. Я не призываю писать все самому, но для такой мелочи RxLib тащить некузяво. Ну, а тем, кто валяется, предлагаю подсказывать, а не валяться. Не боги горшки обжигают.
23.04.2009 13:50
YuraZ
 
Цитата:
OlegON Дело не в велосипеде. В RxLib все уже готовое, но увы, с ошибками. Я даже как-то постил баги где-то. А то, что написано самим собой значительно более проверено и легче правится. Я не призываю писать все самому, но для такой мелочи RxLib тащить некузяво. Ну, а тем, кто валяется, предлагаю подсказывать, а не валяться. Не боги горшки обжигают.
Дык может проще было взять исходник из RXLib, проанализировать и написать самому. Всяко будет полезно проанализировать чужой код.
23.04.2009 14:26
Mihon
 
Цитата:
YuraZ Дык может проще было взять исходник из RXLib, проанализировать и написать самому. Всяко будет полезно проанализировать чужой код.
Никто мне не посоветовал такой компонентик. А рыться в исходнике того, о чем даже не знаешь, по меньшей мере невозможно.
Вообще, проще кинуть RxTrayIcon на форму.

Обязательно всем надо поспорить.
тема такая: ВОТ КОД. кому надо, тот возьмет.
кому не надо, по другому сделает.
А зачем ты такой компонент не взял? А что тут не посмотрел?
А вот не было рядом доброго ангелочка, который насвистывал в ушко:
"Слушай, не ищи в инете "как свернуть программу в трей", тут уже есть компонентик... и пофиг, что это делается 2-мя строчками кода, ведь потом, через год, ты решишь сделать программу, которая целый день будет в трее висеть, и при перезагрузке будут большие проблемы. кинь компонет на форму!"
если бы при поиске решения этой проблемы я наткнулся на форум, где вот так вот все подробно разжевали, я бы был очень рад.

Чем спорить "так лучше, нет так лучше", лучше тогда пример привести, как это с RxTrayIcon делается.
Как ей иконку например выставить. Заменить через время.
Мне уже не надо, у меня все работает.
А вот другим может жизнь облегчит.
Часовой пояс GMT +3, время: 15:47.

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.