![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
проблемы с активизацией приложения [D6, Win2k]
Андрусь © (2002-09-24 17:00:00)Привет всем! Тут вот мучаюсь со следующей проблемой:необх. ограничить число запущенных экземпляров прогр. на одном компьютере до 1-го.Порылся на сайте тут и начал делать так:в проекте создал новый модуль,который в сорсе указал 1-м(будет подгружен 1-м).В нём в секции
initialization
пытаюсь создать мютекс с уник. именем собр. из пути к файлу.Если он уже есть,сл-но один экз. уже запущен.( http://delphi.mastak.ru/articles/limit.html)
Далее я хочу активизировать запущенное ранее приложение. Вот здесь у меня чего-то не отрабатывает.Я делаю так:
(на основании FAQ)
Function FindLastAppl(WndText,ClName:String):hWnd;
Var Wnd : hWnd; buff: Array [0..127] Of Char;WTxt:Boolean;
Begin
Result:=0;
Wnd := GetWindow(Application.Handle, gw_HWndFirst);
While Wnd <> 0 Do
Begin {Не показываем:}
If //(Wnd <> Application.Handle) And {-Собственное окно}
IsWindowVisible(Wnd) And {-Невидимые окна}
(GetWindow(Wnd, gw_Owner) = 0) And {-Дочернии окна}
(GetWindowText(Wnd, buff, sizeof(buff)) <> 0){-без заголовков} Then
Begin
If Pos(WndText, StrPas(buff)) > 0 Then Wtxt:=True
Else Wtxt:=False;
GetClassName(Wnd, buff, sizeof(buff));
If (ClName<>"")Then
If (Pos(ClName, StrPas(buff)) > 0)And Wtxt Then
Begin
Result:=Wnd;
Break;
End;
End;
Wnd := GetWindow(Wnd, gw_hWndNext);
End;
Затем активизируем найденное окно:
//BringWindowToTop(Wnd); тоже как вариант пробовал
ShowWindow(Wnd,SW_ShowNormal);
SetForegroundWindow(Wnd);
Вот. Но почему-то не отрабатывает.Под дебагером смотрел - всё находит,только почему-то не активизируется приложение.
Может кто решал подобную проблему. Может что я делаю не так. Посоветуйте как лучше. Зараннее всем большое спасибо.
Андрусь (2002-09-25 15:43:00) [21]Извините пожалуйста,но чего то не въезжаю - причем здесь Application, который не создан. Я нашёл handle окна,приложения,запущенного раньше. Затем BringWindowToTop-виндозная ф-я.
Простите,мастер,но я не въезжаю - поясните.
Song (2002-09-25 14:12:00) [22]Потому что объект TApplication не создан ещё на тот момент, устал Вам объяснять. :(
Андрусь (2002-09-25 14:05:00) [23]Честно говоря немного не до конца въехал чего вы хотите посоветовать. Скорей всего так я делаю..
program Experimentation;
uses
UOneHInst in "UOneHInst.pas",
Forms,
Unit1 in "Unit1.pas" {Form1};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
У меня проверка в Initialization модуля UOneHinst.
Вот и этого. Чего-то там не отрабатывает BringWindowToTop. Хотя внутри приложения работает.
Song (2002-09-25 13:42:00) [24]Я бы порекомендовал поместить проверку не в Initialization главного модуля, а в dpr
Андрусь (2002-09-25 13:32:00) [25]> Мастер Song ©
Хотябы то чудненько отрабатывает,как с другими виндами.
Отрабатывает в приложении,но в секции Initialization - нет. Делаю я по одной статье(упоминалась выше),так вот там мютекс и проверка идут в initialization отд. модуля, который в программе указан перевым.
unit UOneHInst;
interface
uses
Windows,SysUtils,Forms;
................
initialization
If StopLoading then
Begin
ShowErrMsg;
Wnd:=FindLastAppl("Experimentation", "TApplication")
BringWindowToTop(Wnd);
ShowWindow(Wnd,SW_SHOW);
halt;
End;
finalization
if Mutex <> 0 then
CloseHandle(Mutex);}
end.
Song (2002-09-25 12:41:00) [26]Ну если хэндл нашли, пол дела сделано.
Вот попробуйте хотя бы это: BringWindowToTop()
qube (2002-09-25 12:39:00) [27]нашёл handle нужного окна,осталось одно - активизировать его.
Может быть пойти другим путём?..
А может, послать ему сообщение?
Андрусь (2002-09-25 12:34:00) [28]>DiamondShark
Чего-то в этом духе я и подозревал.
Но всё же.Как мне быть.Необх. исключить вызов второй копии программы - с чем прекрасно справляются мютексы, плюс переключится после попытки запуска второй копии приложения на старую. и чтобы корректно отрабатывала во всех Виндах - тут тоже вроде бы всё победил:нашёл handle нужного окна,осталось одно - активизировать его.
Может быть пойти другим путём?..
DiamondShark (2002-09-25 11:05:00) [29]Ваша проблема -- в особенностях SetForegroundWindow под Win2k.
Там она сделана так, что процесс не может установить окно переднего плана для другого процесса.
kerk (2002-09-24 19:05:00) [30]в RX есть функция ActivatePrevInstance она находится в VCLUtils, она прекрасно работает.
AL2002 (2002-09-24 18:47:00) [31]Тогда временный файл в памяти создать и хватит.
handra (2002-09-24 18:42:00) [32]AL2002 ©> в целях совместимости с Win16, M$ не рекомендует использовать
AL2002 (2002-09-24 18:32:00) [33]А к hPrevInst ты как относишься?
handra (2002-09-24 18:29:00) [34]объяви обработчик сообщения в окне проги и шли его ему:
const
MY_MSG_SHOW = WM_USER + 5563
TForm1=class(TForm)
...
private
procedure FMyMsgShow(var Msg: TMessage); message MY_MSG_SHOW;
...
procedure TForm1.FMyMsgShow(var Msg: TMessage);
begin
//восстанавливаешь здесь свое приложение
end;
В другом приложении SendMessage(НайденныйHWND,MY_MSG_SHOW,0,0);
Андрусь (2002-09-24 18:16:00) [35]А класс окна у всех TApplication... По крайней мере GetClassName давал мне такие(для моих приложений).
Ну про титл: а если он не постоянен.
Song (2002-09-24 18:07:00) [36]2Андрусь © (24.09.02 18:01)
По классу окна.
А я, заметьте про окно ничего и не говорил.
Я говорил про Application.Handle.
Дык вот. Если Вы в программе зададите Application.Title можете по этому Title искать через FindWindow()
Андрусь (2002-09-24 18:01:00) [37]>Song
Это понятно. Но вот у меня ситуация (как и в одном из FAQ),когда нет полного текста окна.Как быть здесь...
Song (2002-09-24 17:42:00) [38]В качестве дискриптора на SetForeGroundWindow() надо передавать Application.Handle того приложения, т.е. просто найти его через FindWindow(). Весь этот цикл не нужен.
Андрусь (2002-09-24 17:24:00) [39]>Дежавюев
Для чего? Для ограничения количества запущенных прог. - так использую.Проблема то в другом.
Дежавюев (2002-09-24 17:13:00) [40]Фигня. Используй Mutex-ы. Просто и сердито!