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

Вниз

Вопрос про SetForegroundWindow   Найти похожие ветки 

 
Демонов Е.В. ©   (2002-10-14 13:54) [0]

Такой вопрос. Раньше приходилось делать программу котора должна была работать в одном экземпляре.
Делал я это при помощи h:=FindWindow(...,...) и если h<>0 то
if isIcon(h) then showWindow(h,Sw_Restore)
else SetForegroundWindow(h).

Всё работало отлично.

Тут на днях я захотел зделать то же самое при помощи MUTEX.

Программа запускается пытается получить дескрипор именнованного MUTEX-а.
Если получила значит одна копия запущена если не поучила значит создаеёт мьютех
с таким именем и с помощью ф-ии RegisterWindowMessage регестрирует сообщение.
и всем окнам с помощью ф-ии broadcastSystemwindow - если не ошибаюсь посылаю всем окнам
сообщение полученное ф-ей RegisterWindowMessage .
В главном окне для реакции на зарегестрированное сообщение перекрываю метод WndProc;
Там пишу:

if registredMesage=msg.msg then
begin
if isIcon(application.handle) then showWindow(application.handle,Sw_Restore)
else SetForegroundWindow(application.handle).// и просто handle пробовал
end
else inherited;


Так вот если окно до выполнения этого кода было свёрнуто то оно разворачивается, а
если не было просто загороженно другими окнами то в панели инструментов соответствующий программе
прямоугольник просто начинает мигать - т.е. становится то тёмным то опять обычным - но
программа не вылазит на передний план.

Я немного поразбирался с этим и пришёл к выводу что окно не может изпользовать
ф-ию setForegroudWindow передав ей application.handle или handle.

Тогда как быть - т.е. как может программа сама себя выдвинуть на передний план.

P.S.: BringToFront пробовал -тоже не работает.


 
Song ©   (2002-10-14 14:27) [1]

У Вас наверно w2k ?


 
Демонов Е.В. ©   (2002-10-14 14:32) [2]

>>Song
>>У Вас наверно w2k ?
Да я это всё проделывал в w2k, но вообще у меня на компе установлен ME и XP - в ME пробовал откомпилированный в w2k файл - от тоже не работает.

А что с w2k есть какието проблемы?



 
Song ©   (2002-10-14 14:36) [3]

Вот у меня вот этот код работает отллично в W9x, NT 4.0 и XP. В w2k не проверял, нету её у меня просто. :-)


IF CheckInstance(NamedMutex)=0 then
Begin
Wnd:=Findwindow(nil,"name");
IF WND<>0 then
Begin
ShowWindow(Wnd,SW_RESTORE);
SetForeGroundWindow(Wnd);
Exit;
End;
End;
Title:="name";


CheckInstance() - ф-ия определения мутекса.


 
Демонов Е.В. ©   (2002-10-14 14:43) [4]

>>Song
В том то и дело что такой код работает - т.е. получение дискриптора по имени и потом SetForeGroundWindow.
Но вы попробуйте в самой программе вызвать SetForeGroundWindow - передав в качестве параметра Handle или Application.Handle , при этом предварительно спрятав окно за другими окнами - у меня ничего не получились.

А просто c помощью посылки зарегестрированного сообщения хотел это проделать. А то с помощью FindWindow - не совсем надёжно если заголовок в программе часто меняется.

А CheckInstance() - это API какаято или просто некоторая функция гдето в коде проверяющая МУТЕКС?


 
Демонов Е.В. ©   (2002-10-14 15:01) [5]

Ну, может кто знает как программа может сама себя выдвинуть на передний план ?


 
Song ©   (2002-10-14 15:11) [6]

>>А то с помощью FindWindow - не совсем надёжно если заголовок в программе часто меняется.
А где Вы видите что я использую заголовок окна? Я использую Tiltle - фактически название объекта TApplication. Его-то Вы не будете менять.

Ещё можно использовать BringWindowToTop()

>>Но вы попробуйте в самой программе вызвать SetForeGroundWindow..
Я Вам говорю. Что после этого у меня ещё отслеживается куча событий, программа много раз прячется, восстанавливается в т.ч. и в трей и всё работает. (этот код у меня в dpr!)


 
saxon ©   (2002-10-14 15:12) [7]

ожет поможет :))
http://delphi.mastak.ru/articles/limit.html


 
Демонов Е.В. ©   (2002-10-14 15:27) [8]

Song
>>Я Вам говорю. Что после этого у меня ещё отслеживается куча событий, программа много раз прячется, восстанавливается в т.ч. и в трей и всё работает. (этот код у меня в dpr!)

У меня тоже работает.
В том то и дело что SetForegroundWindow выполняется из второго экземляра программы передав в качестве параметра Handle окна
или Application.handle первого приложения.


Попробуйте следующее. поместите Timer1 на форму с интервалом 3000 и с кодом OnTimer

SetforеgoundWindow(Handle);// или Application.handle /
timer1.enable:=False;

и кнопку Button1 c кодом onClick
timer1.enable:=true;

А теперь попробуйте нажать на кнопку и специально спрятать окно за другими и ждите 3 секунды. У меня окно не вылазит на верх - а только начинает мигать прямоугольник в панели инструментов.

P.S:как правельно называется энтот прямоугольник в панели инструментов?












 
Демонов Е.В. ©   (2002-10-14 15:32) [9]

2 Song
>>Я использую Tiltle - фактически название объекта TApplication. Его-то Вы не будете менять.

тогда зачем там нужен MUTEX. Если окна нет то FindWindow вернет ноль .



 
Song ©   (2002-10-14 15:34) [10]

Кнопка он называется :-)
То что мигать будет это нормальное действие виндовс, когда активна другая программа и когда последняя имеет фокус ввода.
В том примере что я Вам дал выше именно так и происходит: SetForeGroundWindow() выполняется из второго экземпляра программы и активирует первый экземпляр. Так я и не понял что Вам надо и что у Вас не получается..


 
MegaBass ©   (2002-10-14 16:05) [11]


Комментарий от "Vladimir" (damageinc@e-mail.ru)
Лучше всего использовать именованные мутексы. Главное, пр! идумать
уникальное имя для этого мутекса. Вот пример вполне работоспособной
программы:

program My1;uses Forms, Windows, Dialogs, SysUtils,var g_hAppMutex: THandle; Wnd : hWnd; buff: array [0..127] of Char; s:string; i:integer;function OneInstance: boolean;begin g_hAppMutex:=CreateMutex(nil,false,PChar("AnUniqueString"+IntToStr(GetDesktopWindow))); Result:=(WaitForSingleObject(g_hAppMutex,0)<>WAIT_TIMEOUT);end;begin Application.Initialize; Application.Title := "SmartDecoder"; Application.HelpFile := "Decoder.hlp"; //создаём инстанс, если его ещё нету на текущем рабочем столе g_hAppMutex:=0; if OneInstance then begin
Application.CreateForm(TMainFrm, MainFrm); Application.R!
un; end; if LongBool(g_hAppMutex) then //если уже есть begin ReleaseMutex(g_hAppMutex); CloseHandle(g_hAppMutex); if ParamStr(1)="" then ShowMessage("Программа уже запущена на этом рабочем столе. Нажмите кнопку "OK" для передачи управления уже запущенной копии программы."); Wnd:=GetWindow(GetTopWindow(0),gw_HWndFirst); while Wnd<>0 do begin //Если не собственное и не дочернее окно if (Wnd<>Application.Handle)and(GetWindow(Wnd,gw_Owner)=0) then begin
GetWindowText(Wnd,buff,sizeof(buff!
)); if Copy(StrPas(buff),1,12)="SmartDecoder" then if Wnd=GetWindowLong(Wnd,GWL_USERDATA) then begin ShowWindow(Wnd,SW_ShowNormal); SetForegroundWindow(Wnd); i:=1; while ParamStr(i)<>"" do begin s:=ParamStr(i);
PostMessage(Wnd,WM_OPEN_FILE,GlobalAddAtom(PChar(s)),0); &!
nbsp; inc(i); end; Application.Terminate; Exit; end; end; Wnd:=GetWindow(Wnd,gw_hWndNext); end; end;end.

Если программа уже запущена, управление будет передано существующей
копии.


 
Демонов Е.В. ©   (2002-10-14 16:28) [12]

2MegaBass
нУ ЭТО УЖ СИЛЬНО - Я уж тогда лучше буду FindWindow пользоватся.
Ещё Атомов по добавлял
В статье http://delphi.mastak.ru/articles/limit.html говорится что атомы при аварийном завершении программы не убираются ?!.
А всё ведь опять сводится к перебору заголовков окон. А значит можно и без MUTEX-ов.

P.S.: while ParamStr(i)<>"" do ; Есть же ParamCount - ?.

2Song
>>То что мигать будет это нормальное действие виндовс, когда активна другая программа и когда последняя имеет фокус ввода.

т.е SetForeGroundWindow нормально работает из активной программы ?

>>Я использую Tiltle - фактически название объекта TApplication. Его-то Вы не будете менять.

конечно простой USER не запустит две такие программы - но ведь вам никто не помешает с помощью API изменить TApplication.Title ?


В Итоге мне просто нужнен способ при помощи которого приложение при получении некоторого сообщения покажет себе вверху.

P.S: Кстати , может кто знает для чего нужна SetActiveWindow ? И чем она отличается от SetForeGroundWindow ?




 
Song ©   (2002-10-14 16:32) [13]

Отличия в хэлпе написаны.
BringWindowToTop() пробовали?


 
Демонов Е.В. ©   (2002-10-14 16:52) [14]

>>Song

>>Отличия в хэлпе написаны.
Я что то не очень понял разницу в HELP-е

>>BringWindowToTop() пробовали?
приду домой попробую.


 
Dimka Maslov ©   (2002-10-14 17:05) [15]

Вот процедура, которая "поднимает" форму над всеми окнами

procedure JumpUp;
var
Info:TAnimationInfo;
Animation:LongBool;
hApp: hWnd;
begin
hApp:=Application.Handle;
if IsIconic(hApp) then Application.Restore else begin
SetActiveWindow(hApp);
Info.cbSize:=SizeOf(Info);
if SystemParametersInfo(SPI_GETANIMATION,SizeOf(Info),@Info,0)
then Animation:=Info.iMinAnimate<>0 else Animation:=False;
Info.iMinAnimate:=nFalse;
SystemParametersInfo(SPI_SETANIMATION,SizeOf(Info),@Info,0);
ShowWindow(hApp, SW_MINIMIZE);
ShowWindow(hApp, SW_RESTORE);
Info.iMinAnimate:=integer(Animation);
SystemParametersInfo(SPI_SETANIMATION,SizeOf(Info),@Info,0);
end;
Application.MainForm.Repaint;
end;


 
TTCustomDelphiMaster ©   (2002-10-14 17:32) [16]

Попробуйте так
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_SENDWININICHANGE or SPIF_UPDATEINIFILE);
SetForegroundWindow(form2.Handle);


 
Юрий Зотов ©   (2002-10-14 17:35) [17]

1. В новых версиях Windows такое поведение SetForegroundWindow введено специально. Что будет, если человек работает, например, в Word"e, стучит по клавишам, не глядя на экран, жмет Enter, а в это время фокус получило какое-стороннее окно, которого он не заметил?

Вот поэтому и ввели. Есть недокументированная функция SwitchToThisWindow, которая обходит эту фичу, но лучше пользоваться легальными средствами.

2. Вот здесь написано, как сделать программу, не допускающую своего повторного запуска - без всяких FindWindow и SetForegroundWindow.

http://www.delphikingdom.com/helloworld/samples_win.htm


 
Демонов Е.В. ©   (2002-10-14 17:52) [18]

2Юрий Зотов
>>В новых версиях Windows такое поведение SetForegroundWindow введено специально.

какое именно поведение? Т.е. SetForegroundWindow работает "нормально" Если его вызвало активное в данный момент приложение ?


 
Юрий Зотов ©   (2002-10-14 18:05) [19]

Ваши собственные слова:

"в панели инструментов соответствующий программе прямоугольник просто начинает мигать - т.е. становится то тёмным то опять обычным - но программа не вылазит на передний план".


 
roadster   (2002-10-15 10:05) [20]

Я тоже подобное писал
Это винды так реагируют, причем 95-й окно выплевывает, а 98-й моргает, это на примере других прог видно
как говорят в мелкософтовском суппорте, это не у нас глюка, это у вас версия старая :0)



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

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

Наверх




Память: 0.53 MB
Время: 0.025 c
7-78698
Сережа
2002-08-16 09:27
2002.10.24
Закрытие Windows


1-78386
dix mod
2002-10-15 09:28
2002.10.24
Двоичные деревья


3-78266
AlexeyMir
2002-10-01 12:03
2002.10.24
DBDesktop - русский шрифт


14-78662
Nox
2002-10-04 18:24
2002.10.24
Дельфи - это сила


7-78695
TsaturSoft
2002-08-13 22:20
2002.10.24
Иконка каталога