Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
3-78267
sdram
2002-10-02 16:22
2002.10.24
Помогите выполнить Refresh


1-78404
Cosinus
2002-10-15 12:55
2002.10.24
Вопрос по работе с DrawGrid


1-78417
TAN
2002-10-15 16:18
2002.10.24
как в TreeView узнатть индекс выделенного узла?


3-78304
UncleRu
2002-10-02 20:40
2002.10.24
картинки в Oracle9i


1-78337
NewChainik
2002-10-14 13:35
2002.10.24
Как обратиться к переменной, если ее имя задано текстовой строкой





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский