Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Показ формы-оповещения без фокуса


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]

Как форма скрывается ?


Наверх

Титульная страница Поиск, карта сайта Написать письмо