Форум: "Основная";
Текущий архив: 2002.10.24;
Скачать: [xml.tar.bz2];
ВнизВопрос про 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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.008 c