![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Показ формы-оповещения без фокуса
shmelina © (2007-09-14 12:23:00)Есть такая задача.
Работает программа. В фоновом режиме она проверяет наличие некоторых событий. Если событие есть, то показывается специальная форма-оповещение. Но форма эта должна отображаться в панели задач и не должна забирать на себя фокус. Кроме того:
- если форма на заднем фоне (на главным окном), то при наступлении события она должна показываться (не беря на себя фокус опять же)
- если форма оповещения свернута, то при наступлении события она должна показываться (не беря на себя фокус)
- если форма оповещения закрыта (но висит в памяти), то при наступлении события она должна показываться (не беря на себя фокус)
- если пользователь работает в другом приложении, то при наступлении события она должна показываться (не беря на себя фокус)
- форма не должна быть модальной или иметь признак "всегда сверху"
Что пока получилось:
- В панели задачи мы сидим.
- Первый показ окна оповещения срабатывает (после Create).
Не получилось:
- Второй и следующие показы не хотят показывать окно. Оно остается на заднем фоне.
Как в панель задач пихал окно писать не буду, оно вроде понятно.
Окно оповещения создается так:
Form.Create(nil);
Причем создается один раз и не уничтожается, пока не закроют программу. Так надо!
Показывается окно так:
ShowWindow(Form.Handle, SW_SHOWNOACTIVATE);
Form.Visible := True;
Первый показ происходит правильно, остальные - нет. Эксперименты с использование метода тыка не помогли.
Помогите пожалуйста.
shmelina (2007-09-17 15:29:00) [1]А можно обойтись без этого? А заметил, что при закрытии окна оповещения иногда идет подвисание.
if IsWindow(FSaveForeground) then
begin
{ AttachThreadInput(
GetWindowThreadProcessId(Handle, nil),
GetWindowThreadProcessId(FSaveForeground, nil),
True); }
SetForegroundWindow(FSaveForeground)
end;
shmelina (2007-09-17 15:15:00) [2]Все, разобрался. Спасибо!
shmelina (2007-09-17 14:58:00) [3]Хотя нет, торможу. Все работает почти как надо. Только при сворачивании оповещения появляется приложение оповещения.
Lacmus (2007-09-17 14:52:00) [4]Считаем, что фокус все-таки нужен
FSaveForeground: THandle;
public
{ Public declarations }
procedure CreateParams(var aParams: TCreateParams); override;
procedure ShowByEvent;
end;
var
Form58: TForm58;
implementation
{$R *.dfm}
procedure TForm58.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if IsWindow(FSaveForeground) then begin
AttachThreadInput(GetWindowThreadProcessId(Handle, nil),
GetWindowThreadProcessId(FSaveForeground, nil), True);
SetForegroundWindow(FSaveForeground)
end
end;
procedure TForm58.CreateParams(var aParams: TCreateParams);
begin
inherited;
aParams.WndParent := GetDesktopWindow
end;
procedure TForm58.ShowByEvent;
begin
FSaveForeground := GetForegroundWindow;
AttachThreadInput(GetWindowThreadProcessId(FSaveForeground, nil),
GetWindowThreadProcessId(Handle, nil), True);
SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0,
SWP_NOMOVE or SWP_NOSIZE or SWP_SHOWWINDOW or SWP_NOACTIVATE);
Visible := True;
end;
shmelina (2007-09-17 14:44:00) [5]Кстати, на тестовом приложении с пустыми формами после закрытия оповещения фокус возвращается приложению, в котором я работал. А в реальной программе - нет =(. Но все равно спасибо за помощь. В любом случае лучше стало, чем было.
shmelina (2007-09-17 14:21:00) [6]Спасибо, осталось совсем чуть-чуть. =)
При клике на форму оповещения (не на заголовок, а на саму форму!) она не ловит фокус.
Lacmus (2007-09-14 17:58:00) [7]Еще вариант
{ unit58 }
implementation
{$R *.dfm}
procedure TForm58.FormCreate(Sender: TObject);
begin
ParentWindow := GetDesktopWindow
end;
end.
shmelina (2007-09-14 17:38:00) [8]Теперь при клике на заготовок формы58 рамка не отображает фокус.
А если кликнуть на саму форму, то фокус ловится, но при закрытии крестиком опять приложение оповещения появляется.
Lacmus (2007-09-14 17:07:00) [9]
procedure WMMouseActivate(var aMessage: TMessage); message WM_MOUSEACTIVATE;
procedure TForm58.WMMouseActivate(var aMessage: TMessage);
begin
aMessage.Result := MA_NOACTIVATE
end;
shmelina (2007-09-14 17:02:00) [10]Может и проще. Но переделок много.
В принципе полученного результата по минимуму хватает. Можно не нажимать крестик, а сворачивать оповещение. Так вроде все работает как надо. Если с крестиком не победим, то оставлю как есть =(.
Anatoly Podgoretsky (2007-09-14 16:57:00) [11]> Котик Б (14.09.2007 16:53:07) [7]
> А не проще ли сделать tray + hint ?
BallonHint
Котик Б (2007-09-14 16:53:00) [12]А не проще ли сделать tray + hint ?
shmelina (2007-09-14 16:41:00) [13]Спасибо! У меня тоже получилось, но несколько по другому сделано:
SetWindowPos(Form.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOOWNERZORDER);
SetWindowPos(Form.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOOWNERZORDER);
AlarmForm.Visible := True;
Однако есть еще проблема (у тебя и у меня):
Находясь в другом приложение появляется (без фокуса) форма оповещения. Но при закрытии ее крестиком всплывает приложение от оповещения.
Как быть?
Lacmus (2007-09-14 16:05:00) [14]
procedure TForm57.Timer1Timer(Sender: TObject);
begin
AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow, nil),
GetWindowThreadProcessId(Form58.Handle, nil), True);
SetWindowPos(Form58.Handle, HWND_TOP, 0, 0, 0, 0,
SWP_NOMOVE or SWP_NOSIZE or SWP_SHOWWINDOW or SWP_NOACTIVATE);
Form58.Visible := True;
end;
{ unit Unit58 }
...
procedure CreateParams(var aParams: TCreateParams); override;
end;
var
Form58: TForm58;
implementation
{$R *.dfm}
procedure TForm58.CreateParams(var aParams: TCreateParams);
begin
inherited;
aParams.WndParent := GetDesktopWindow
end;
Хотя тоже есть некоторые проблемы, но условия shmelina © (14.09.07 12:23) вроде выполняются.
shmelina (2007-09-14 14:53:00) [15]Ты показываешь окно по кнопке ИЗ СВОЕГО ПРИЛОЖЕНИЯ. А ты подцепи таймер - пусть само показывается. И не забудь в другое приложение переключиться.
Окно оповещения должно появляться в какой программе вы бы не находились!
Lacmus (2007-09-14 14:44:00) [16]
procedure TForm57.Button1Click(Sender: TObject);
begin
ShowWindow(Form58.Handle, SW_SHOWNOACTIVATE);
Form58.Visible := True
end;
procedure TForm57.Button2Click(Sender: TObject);
begin
Form58.Close
end;
Проблем нет
shmelina (2007-09-14 14:35:00) [17]Close;
Lacmus (2007-09-14 13:40:00) [18]Как форма скрывается ?