Форум: "WinAPI";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];
ВнизКак активировать уже запущенную копию приложения? Найти похожие ветки
← →
novice__man (2005-01-22 19:45) [0]В общем дело обстоит так:
Мне нужно, что бы было невозможно запустить вторую копию приложения, что в принципе сделано. Вот только хотелось бы что бы при этом событии уже запущенная копия приложения дала о себе знать (либо помигала кнопкой в панеле задачь, либо вышла на передний план), в общем пользователь увидел, что приложение уже работает и вот оно!
← →
Eraser © (2005-01-22 20:18) [1]Один из способов. Отсылка сообщения уже запущеному приложению, которое оповещает о запуске его второй копии.
← →
vertal © (2005-01-23 02:28) [2]Если в вашем приложении все время существует какое-то окно, то можно по SetForegroundWindow(FindWindow(YourWndClass, YourWndName))
← →
Leonid Troyanovsky © (2005-01-23 02:54) [3]
> vertal © (23.01.05 02:28) [2]
> Если в вашем приложении все время существует какое-то окно,
> то можно по SetForegroundWindow(FindWindow(YourWndClass,
> YourWndName))
Это надо делать не c самим окном, а с окном приложения,
т.е. wnd := HWND(GetWindowLong(wnd, GWL_HWNDPARENT)).
Ну, а окно главной формы всегда существует.
Если, конечно, приложение не бесформенное ;)
--
Regards, LVT.
← →
Просто Джо © (2005-01-23 03:17) [4]
SetForegroundWindow(H);
?
← →
Erik1 © (2005-01-24 11:39) [5]Только ненадо пожалуста ерунды с окнами, всеравно работать небудет!
var
ObjName: PChar;
Handle: THandle;
AppWnd: HWnd;
IsTerm: boolean;
const
UnicName = "Starvara";
Duplicate = "duplicate";
begin
DateSeparator := ".";
IsTerm := IsTerminal;
if not FindCmdLineSwitch(Duplicate, ["-", "/"], true) and not IsTerm then
begin
GetMem(ObjName, Length(UnicName) + 1);
try
StrCopy(ObjName, UnicName);
Handle := CreateMutex(nil, true, ObjName);
finally
FreeMem(ObjName);
end;
if ((Handle <> 0) and (getLastError() = ERROR_ALREADY_EXISTS)) then
begin
AppWnd := 0;
repeat
AppWnd := FindWindowEx(0, AppWnd, "TApplication", PChar(UnicName));
until AppWnd <> Application.Handle;
if AppWnd <> 0 then
begin
if IsIconic(AppWnd) then
ShowWindow(AppWnd, SW_Restore)
else
SetForegroundWindow(AppWnd);
end;
Halt;
end;
end; {isTerm}
← →
Eraser © (2005-01-24 12:33) [6]Настаиваю на своём мнении, что нужно передовать своё (пользовательское) сообщение.
Что вы например будете делать, если новую копию приложения запустят с параметром, в котором указывается, например, имя файла, который нужно открыть. Можно конечно на это наплевать, но все серьёзные программы открывают файл (см. MSWord, Delphi). Для этого посылается сообщение главному экземпляру приложения с этим параметром.
Надеюсь не сильно путанное объяснение ;-)
← →
GrayFace © (2005-01-26 17:25) [7]Помигать кнопкой в панеле задачь - FlashWindow.
Можно просто использовать TELInstanceChecker из Extension Lib. Хотя, там, похоже есть один глюк.
Erik1 © (24.01.05 11:39) [5]
Только ненадо пожалуста ерунды с окнами, всеравно работать небудет!
Будет, только криво.
Erik1 © (24.01.05 11:39) [5]
GetMem(ObjName, Length(UnicName) + 1);
try
StrCopy(ObjName, UnicName);
Handle := CreateMutex(nil, true, ObjName);
finally
FreeMem(ObjName);
end;
А не лучше лиvar s:string; s:=UnicName;
? (как я понял из кода, CreateMutex требует не Readonly строку) На всякий случай можноSetString(s, UnicName, length(UnicName));
Erik1 © (24.01.05 11:39) [5]
AppWnd := 0;
repeat
AppWnd := FindWindowEx(0, AppWnd, "TApplication", PChar(UnicName));
until AppWnd <> Application.Handle;
Как я понимаю, Application.Title должен быть равен UnicName? Тогда все это теряет смысл.
Eraser © (24.01.05 12:33) [6]
Просто SetForegroundWindow не сработает, если вызывать из неактивного экземпляра.
← →
GrayFace © (2005-01-26 17:26) [8]GrayFace © (26.01.05 17:25) [7]
Хотя, там, похоже есть один глюк.
Нет. Это я проглючил.
← →
Gero © (2005-01-26 17:27) [9]
> Только ненадо пожалуста ерунды с окнами, всеравно работать
> небудет!
> repeat
> AppWnd := FindWindowEx(0, AppWnd, "TApplication",
> PChar(UnicName));
> until AppWnd <> Application.Handle;
> if AppWnd <> 0 then
> begin
> if IsIconic(AppWnd) then
> ShowWindow(AppWnd, SW_Restore)
> else
> SetForegroundWindow(AppWnd);
> end;
А что это за ерунда с окнами?
← →
novice__man (2005-01-26 17:41) [10]
var
PrevCopy: DWORD;
begin
Application.ShowMainForm := False;
PrevCopy := BSM_APPLICATIONS;
BroadCastSystemMessage(BSF_IGNORECURRENTTASK or SF_POSTMESSAGE, @PrevCopy, MessageID, 0, 0);
end;
А так можно?
← →
GrayFace © (2005-01-27 16:11) [11]novice__man (26.01.05 17:41) [10]
Еще надо создавать, например, атом, чтобы узнать, запущено ли приложение.
novice__man (26.01.05 17:41) [10]
Application.ShowMainForm := False;
????
← →
novice__man (2005-01-27 16:17) [12]GrayFace © (27.01.05 16:11) [11]
Application.ShowMainForm := False;
????
Понял, исправлюсь, в этот момент нет еще главной формы приложения.
Еще надо создавать, например, атом, чтобы узнать, запущено ли приложение.
Атом создан раньше, это только индикация об уже запущенном приложении.
← →
GrayFace © (2005-01-27 17:36) [13]novice__man (27.01.05 16:17) [12]
Понял, исправлюсь, в этот момент нет еще главной формы приложения.
Я, кажется, тоже понял. Этот код - в OnCreate, а в другом месте ты делаешь MainForm.Close? Или это в .dpr до Application.CreateForm-ов?
← →
alpet (2005-01-27 17:43) [14]>Просто SetForegroundWindow не сработает, если вызывать из неактивного экземпляра.
Надо перед этим вызвать AttachThreadInput, тогда обязательно сработает.
← →
Eraser © (2005-01-28 15:24) [15]novice__man
Установи пакет компонентов JVCL, там есть компонент который отлично справляется с твоей задачей. Проверено.
← →
Eraser © (2005-01-28 15:39) [16]novice__man
Установи пакет компонентов JVCL, там есть компонент который отлично справляется с твоей задачей. Проверено.
← →
Eraser © (2005-01-28 15:39) [17]novice__man
Установи пакет компонентов JVCL, там есть компонент который отлично справляется с твоей задачей. Проверено.
← →
novice_man © (2005-01-28 16:03) [18]Eraser © (28.01.05 15:24) [15]
novice__man
Установи пакет компонентов JVCL, там есть компонент который отлично справляется с твоей задачей. Проверено.
Спасибо за предложение. Но у меня все работает, спасибо интернету :), бездна информации.
А насчет дополнительных компонентов, то мне не очень нравится их использовать в своих проектах, но как справочная информация и пример реализации (если конечно они с исходниками) они мне подходят.
GrayFace © (27.01.05 17:36) [13]
Я вызываю функцию проверки в модуле project.dprif CheckPrevCopy then
Application.Initialize;
Application.Title := "my_project";
Application.CreateForm(TForm, Form1);
Application.Run;
end else Halt;
может сдесь и не все правильно, но пока я только до этого дошел, может со временем все прийдется пересмотреть.
← →
novice_man © (2005-01-28 16:06) [19]Eraser © (28.01.05 15:24) [15]
novice__man
Установи пакет компонентов JVCL, там есть компонент который отлично справляется с твоей задачей. Проверено.
Спасибо за предложение. Но у меня все работает, спасибо интернету :), бездна информации.
А насчет дополнительных компонентов, то мне не очень нравится их использовать в своих проектах, но как справочная информация и пример реализации (если конечно они с исходниками) они мне подходят.
GrayFace © (27.01.05 17:36) [13]
Я вызываю функцию проверки в модуле project.dprif CheckPrevCopy then
Application.Initialize;
Application.Title := "my_project";
Application.CreateForm(TForm, Form1);
Application.Run;
end else Halt;
может сдесь и не все правильно, но пока я только до этого дошел, может со временем все прийдется пересмотреть.
← →
Eraser © (2005-01-28 16:45) [20]novice_man ©
Безусловно, сделать код который определяет вторую копию и делает её активной не сложно. Проблемы возникнут при передачи параметров запуска второй копии.
← →
Георгий Бедный (2005-01-28 18:58) [21]А как заставить прогу прочитать командную строку (ParamStr) другой копии приложения??
← →
novice_man © (2005-01-28 19:06) [22]Eraser © (28.01.05 16:45) [20]
Модет тут то и пригодится отсылка сообщения предидущей копии программы?
← →
vertal © (2005-01-28 22:46) [23]> GrayFace © (27.01.05 16:11) [11]
> Еще надо создавать, например, атом, чтобы узнать, запущено ли
приложение.
Я бы так делать не стал, так как при нештатном завершении приложения этот атом не уничтожается системой и соотв. при сбое юзер больше не сможет запустить ваше приложение в текущем сеансе работы с Win, если оно будет проверять существование своей предыдущей копии по наличию атома. А мьютекс удаляется автоматически.
← →
Johnmen © (2005-01-29 03:49) [24]>novice_man ©
Примерно так:
const
StartEvent: string= "MySuperPuperProgramm";
procedure ActivateOldInstance;
var
FoundWindow, FoundPopup : THandle;
begin;
try;
FoundWindow:=FindWindow(nil,PChar(AppTitle));
if FoundWindow<>0 then begin;
FoundPopup:=GetLastActivePopup(FoundWindow);
if IsIconic(FoundWindow) then ShowWindow(FoundWindow,SW_RESTORE);
BringWindowToTop(FoundWindow);
SetForegroundWindow(FoundWindow);
if FoundPopup<>0 then begin;
if IsIconic(FoundPopup) then ShowWindow(FoundPopup,SW_RESTORE);
BringWindowToTop(FoundPopup);
SetForegroundWindow(FoundPopup);
end;
end;
except end;
end;
begin;
SetLastError(0);
CreateEvent(nil,true,true,PChar(StartEvent));
if GetLastError<>0 then ActivateOldInstance
else begin;
....
← →
GrayFace © (2005-01-29 04:35) [25]alpet (27.01.05 17:43) [14], vertal © (28.01.05 22:46) [23]
Сэнкс.
novice_man © (28.01.05 16:03) [18]
if CheckPrevCopy then
Application.Initialize;
Application.Title := "my_project";
Application.CreateForm(TForm, Form1);
Application.Run;
end else Halt;
А зачем Halt?
← →
Георгий Бедный (2005-01-29 13:17) [26]Ну, это даже я знаю! :) Halt - это значит не запускать приложение. :lol:
Дайте мне, плиз, пример отправки-приёма сообщения предыдущей копии программы (например, когда я через системное меню винды открываю этой прогой сразу несколько файлов, она должна составить себе лист из них, т. е. все по сути командлайны стекаются в виде отфутболенных сообщений самой первой копии приложения, и она их группирует в список)!
← →
GrayFace © (2005-01-30 05:21) [27]Георгий Бедный (29.01.05 13:17) [26]
Ну, это даже я знаю! :) Halt - это значит не запускать приложение. :lol:
Нет. Halt - это значит завершить приложение. А зачем завершать приложение, если на следующей строчке, скорее всего, стоит "end." и оно все-равно завершится?
← →
novice_man © (2005-01-30 05:51) [28]GrayFace © (30.01.05 05:21) [27]
В принципе Вы правы и HALT здесь особой роли не играет.
← →
Георгий Бедный (2005-01-30 17:34) [29]Круто. Только непонятки со списком файлов (как, например, в Винампе).
← →
GrayFace © (2005-01-31 19:58) [30]Георгий Бедный (30.01.05 17:34) [29]
Можно использовать TELInstanceChecker из Extension Lib. Он с исходниками - можно и посмотреть, как это там делается.
← →
remb (2005-01-31 21:22) [31]http://i-s-v.org.ua/
программа QLoader 1.4
← →
Erik1 © (2005-02-01 12:22) [32]Вобщето я использовал мьютекс для определения запущена прошрамма или нет, а далее едет работа с окнами потому, что точно известно о старете другой копии. Поэтому работа с окнами на данном этапе совершенно безопасна. А то что UnicName = названию окна, так это мне удобнее, поскольку объект Applecation еще не нинициализирован.
← →
GrayFace © (2005-02-01 17:21) [33]Но ведь имя приложения - штука не очень уникальная. А зачем Mutex, если все-равно окна ищутся?
← →
Владислав © (2005-02-01 19:03) [34]Вот еще вариант.
PFirstCopyInfo = ^TFirstCopyInfo;
TFirstCopyInfo = record
Window: HWND
end;
//*****************
const
G_FirstCopyMapSize = SizeOf(TFirstCopyInfo);
var
G_HFirstCopyMap: Cardinal = 0;
function AnotherCopyExists: Boolean;
begin
G_HFirstCopyMap :=
CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE or SEC_COMMIT,
0, G_FirstCopyMapSize, G_SFirstCopyMapName);
Result := GetLastError = ERROR_ALREADY_EXISTS;
if G_HFirstCopyMap = 0 then
Exit;
G_LPFirstCopyInfo :=
MapViewOfFile(G_HFirstCopyMap, FILE_MAP_WRITE, 0, 0, G_FirstCopyMapSize);
G_ActivateAnotherCopyMsg := RegisterWindowMessage(G_ActivateAnotherCopyMsgName)
end;
procedure CloseFirstCopyInfo;
begin
if G_LPFirstCopyInfo <> nil then
begin
UnmapViewOfFile(G_LPFirstCopyInfo);
G_LPFirstCopyInfo := nil
end;
if G_HFirstCopyMap <> 0 then
begin
CloseHandle(G_HFirstCopyMap);
G_HFirstCopyMap := 0
end
end;
begin
if AnotherCopyExists then
begin
if G_LPFirstCopyInfo <> nil then
begin
with G_LPFirstCopyInfo^ do
if (Window <> 0) and (G_ActivateAnotherCopyMsg <> 0) then
PostMessage(Window, G_ActivateAnotherCopyMsg, 0, 0)
end;
CloseFirstCopyInfo;
Exit
end;
Application.Initialize;
Application.ShowMainForm := False;
Application.CreateForm(TdmMain, dmMain);
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
CloseFirstCopyInfo
end.
← →
Владислав © (2005-02-01 19:06) [35]Забыл...
Две глобальные переменные:
G_LPFirstCopyInfo: PFirstCopyInfo = nil;
G_ActivateAnotherCopyMsg: Cardinal = 0;
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.057 c