-
Как я понимаю, при создании TrayIcon вот таким образом NewTrayIcon(frmMain, frmMain.Icon) в качестве первого параматра мы передаем родителя, к функции окна которого мы прикрепим функцию окна нашего TrayIcon, на это указывает строчка из NewTrayIcon - Wnd.AttachProc( WndProcTray ). Далее если посмотреть WndProcTray то видно что мы перехватываем WM_CLOSE и в итоге удаляем иконку из трея. Это дает нам возможность при закрытии формы, автоматически удалять и иконку. 1) Но при этом появляется проблема, так как (указано в описании AttachProc) «Last attached procedure is called first», то если мы захотим «не реагировать на закрытие формы», например установив Accept := False в OnClose, сообщение WM_CLOSE все равно попадет в WndProcTray, и все нам испортит :( 2) Если же не передавать главную форму в NewTrayIcon (в инете есть пример работы с TrayIcon где в NewTrayIcon передается не форма а созданый PControl), то в результате при закрытии главной формы иконка не удаляется из трея.
Что по вашему мнению более разумно сделать в этих ситуациях?
-
первая проблема актуальна также, если использовать главную форму и TrayIcon, при этом разрабатывая приложение с помощью MCK. Потому что в этом случае MCK генерирует код который в качестве первого параметра NewTrayIcon передает главную форму
-
Вообще интересует как при минимизации и закрытии формы просто скрыть ее.
-
Пока что пришел к такому: procedure DoFormClose(Dummy: Pointer; Sender: PObj; var Accept: Boolean);
begin
if frmMain.Visible then begin
frmMain.Hide;
Accept := False;
end else begin
Tray.Free;
Accept := True;
end;
end;
procedure DoWorkMenu(Dummy: Pointer; Sender: pMenu; Item: Integer);
begin
case Item of
...
2: frmMain.Close;
end;
end;
...
frmMain.OnClose := TOnEventAccept(MakeMethod(nil, @DoFormClose));
...
Menu := NewMenu(frmMain, 0,
['Show/Hide',
'-',
'Exit' ],
TOnMenuItem(MakeMethod(nil, @DoWorkMenu))
);
...
Tray.NoAutoDeactivate := True; Это позволяет скрывать форму при нажатии кнопки «Закрыть» и при этом корректно удалять иконку при выходе из программы.
-
Появилась проблема :( Если мы хотим выйти из программы с помощью меню трея, и при этом форма не скрыта, то она просто скрывается :(
-
var
AppExit: Boolean = False;
procedure DoWorkMenu(Dummy: Pointer; Sender: pMenu; Item: Integer);
begin
case Item of
0: ShowHideForm;
2: begin
AppExit := True;
frmMain.Close;
end;
end;
end;
procedure DoFormClose(Dummy: Pointer; Sender: PObj; var Accept: Boolean);
begin
if optCloseToHide and frmMain.Visible and not AppExit then begin
frmMain.Hide;
Accept := False;
end else begin
Tray.Free;
Accept := True;
end;
end;
-
program testFormHide;
uses
Windows, Messages, KOL;
type
PForm1 = ^TForm1;
TForm1 = object(TObj)
private
Form: PControl;
TI: PTrayIcon;
Menu: PMenu;
function FormMessage(var Msg: TMsg; var Rslt: Integer): Boolean;
procedure TIMouse(Sender: PObj; Message: Word);
procedure MenuMenuItem(Sender: PMenu; Item: Integer);
end;
var Form1: PForm1;
const
WM_SHOWHIDE = WM_USER + 1000;
function TForm1.FormMessage(var Msg: TMsg; var Rslt: Integer): Boolean;
begin
Result := False;
case Msg.message of
WM_SYSCOMMAND: begin
case Msg.wParam of
SC_CLOSE, SC_MINIMIZE: begin
Form.Perform(WM_SHOWHIDE, 0, 0);
Result := True;
end;
end;
end;
WM_SHOWHIDE: begin
if Form.Visible then
begin
Form.Hide;
Menu.ItemText[0] := 'Show';
end
else begin
Form.Show;
Menu.ItemText[0] := 'Hide';
end;
end;
end;
end;
procedure TForm1.MenuMenuItem(Sender: PMenu; Item: Integer);
begin
case Item of
0: Form.Perform(WM_SHOWHIDE, 0, 0);
2: Form.Close;
end;
end;
procedure TForm1.TIMouse(Sender: PObj; Message: Word);
var P: TPoint;
begin
case Message of
WM_RBUTTONUP:begin
SetForegroundWindow(Form.Handle);
GetCursorPos(P);
Menu.Popup(P.X, P.Y);
end;
WM_LBUTTONDOWN:
SetForegroundWindow(Form.Handle);
WM_LBUTTONDBLCLK:
Form.Perform(WM_SHOWHIDE, 0, 0);
end;
end;
begin
New(Form1, Create);
with Form1^ do
begin
Form := NewForm(nil, 'Test');
Form.Add2AutoFree(Form1);
Form.OnMessage := FormMessage;
TI := NewTrayIcon(Form, LoadIcon(0, IDI_APPLICATION));
TI.OnMouse := TIMouse;
NewMenu(Form, 0, [], nil);
Menu := NewMenu(Form, 0, ['Hide', '-', 'Exit'], MenuMenuItem);
Menu.Items[0].DefaultItem := True;
Run(Form);
end;
end.
-
Спасибо! :) Сам как раз разобрался и пришел к такому: function DoFormMessage(Dummy: Pointer; var Msg: TMsg; var Rslt: Integer): Boolean;
begin
Result := False;
if Msg.message = WM_SYSCOMMAND then
case Msg.wParam of
SC_MINIMIZE:
if optMinToHide then begin
frmMain.Hide;
Result := True;
end;
SC_CLOSE:
if optCloseToHide then begin
frmMain.Hide;
Result := True;
end
end;
end; Действительно лучше ловить не WM_Close, а SC_CLOSE НО Ваш пример много чего для меня показывает, например организация кода без использования MCK :) Вопрос, зачем использовать SHOWHIDE, а не вызывать сразу процедуру ShowHide?
-
> Вопрос, зачем использовать SHOWHIDE, а не вызывать сразу > процедуру ShowHide?
В данном случае - незачем.
|