Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.10.14;
Скачать: CL | DM;

Вниз

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

 
shmelina ©   (2007-09-14 12:23) [0]

Есть такая задача.
Работает программа. В фоновом режиме она проверяет наличие некоторых событий. Если событие есть, то показывается специальная форма-оповещение. Но форма эта должна отображаться в панели задач и не должна забирать на себя фокус. Кроме того:
- если форма на заднем фоне (на главным окном), то при наступлении события она должна показываться (не беря на себя фокус опять же)
- если форма оповещения свернута, то при наступлении события она должна показываться (не беря на себя фокус)
- если форма оповещения закрыта (но висит в памяти), то при наступлении события она должна показываться (не беря на себя фокус)
- если пользователь работает в другом приложении, то при наступлении события она должна показываться (не беря на себя фокус)
- форма не должна быть модальной или иметь признак "всегда сверху"

Что пока получилось:
- В панели задачи мы сидим.
- Первый показ окна оповещения срабатывает (после Create).

Не получилось:
- Второй и следующие показы не хотят показывать окно. Оно остается на заднем фоне.

Как в панель задач пихал окно писать не буду, оно вроде понятно.

Окно оповещения создается так:
 Form.Create(nil);
Причем создается один раз и не уничтожается, пока не закроют программу. Так надо!

Показывается окно так:
 ShowWindow(Form.Handle, SW_SHOWNOACTIVATE);
 Form.Visible := True;

Первый показ происходит правильно, остальные - нет. Эксперименты с использование метода тыка не помогли.

Помогите пожалуйста.


 
Lacmus ©   (2007-09-14 13:40) [1]

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


 
shmelina ©   (2007-09-14 14:35) [2]

Close;


 
Lacmus ©   (2007-09-14 14:44) [3]



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:53) [4]

Ты показываешь окно по кнопке ИЗ СВОЕГО ПРИЛОЖЕНИЯ. А ты подцепи таймер - пусть само показывается. И не забудь в другое приложение переключиться.

Окно оповещения должно появляться в какой программе вы бы не находились!


 
Lacmus ©   (2007-09-14 16:05) [5]



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 16:41) [6]

Спасибо! У меня тоже получилось, но несколько по другому сделано:


 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;


Однако есть еще проблема (у тебя и у меня):
Находясь в другом приложение появляется (без фокуса) форма оповещения. Но при закрытии ее крестиком всплывает приложение от оповещения.

Как быть?


 
Котик Б   (2007-09-14 16:53) [7]

А не проще ли сделать tray + hint ?


 
Anatoly Podgoretsky ©   (2007-09-14 16:57) [8]

> Котик Б  (14.09.2007 16:53:07)  [7]

> А не проще ли сделать tray + hint ?

BallonHint


 
shmelina ©   (2007-09-14 17:02) [9]

Может и проще. Но переделок много.
В принципе полученного результата по минимуму хватает. Можно не нажимать крестик, а сворачивать оповещение. Так вроде все работает как надо. Если с крестиком не победим, то оставлю как есть =(.


 
Lacmus ©   (2007-09-14 17:07) [10]


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:38) [11]

Теперь при клике на заготовок формы58 рамка не отображает фокус.
А если кликнуть на саму форму, то фокус ловится, но при закрытии крестиком опять приложение оповещения появляется.


 
Lacmus ©   (2007-09-14 17:58) [12]

Еще вариант

{ unit58 }

implementation

{$R *.dfm}

procedure TForm58.FormCreate(Sender: TObject);
begin
 ParentWindow := GetDesktopWindow
end;

end.


 
shmelina ©   (2007-09-17 14:21) [13]

Спасибо, осталось совсем чуть-чуть. =)
При клике на форму оповещения (не на заголовок, а на саму форму!) она не ловит фокус.


 
shmelina ©   (2007-09-17 14:44) [14]

Кстати, на тестовом приложении с пустыми формами после закрытия оповещения фокус возвращается приложению, в котором я работал. А в реальной программе - нет =(. Но все равно спасибо за помощь. В любом случае лучше стало, чем было.


 
Lacmus ©   (2007-09-17 14:52) [15]

Считаем, что фокус все-таки нужен



   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:58) [16]

Хотя нет, торможу. Все работает почти как надо. Только при сворачивании оповещения появляется приложение оповещения.


 
shmelina ©   (2007-09-17 15:15) [17]

Все, разобрался. Спасибо!


 
shmelina ©   (2007-09-17 15:29) [18]

А можно обойтись без этого? А заметил, что при закрытии окна оповещения иногда идет подвисание.

 if IsWindow(FSaveForeground) then
 begin
{    AttachThreadInput(
     GetWindowThreadProcessId(Handle, nil),
     GetWindowThreadProcessId(FSaveForeground, nil),
     True); }

   SetForegroundWindow(FSaveForeground)
 end;



Страницы: 1 вся ветка

Текущий архив: 2007.10.14;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.024 c
2-1190314315
qadeveloper2
2007-09-20 22:51
2007.10.14
Ссылка?


2-1189625872
aids
2007-09-12 23:37
2007.10.14
матрица


3-1181296206
MZ
2007-06-08 13:50
2007.10.14
Триггер или COUNT?


1-1185876101
hug
2007-07-31 14:01
2007.10.14
Выбор элемента TTreeView с помощью галочки


2-1189853106
ProgRAMmer Dimonych
2007-09-15 14:45
2007.10.14
Снова проблемы (вырезка элементов массива)