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

Вниз

Как активировать уже запущенную копию приложения?   Найти похожие ветки 

 
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.dpr

if 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.dpr

if 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 вся ветка

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

Наверх




Память: 0.57 MB
Время: 0.049 c
1-1109762690
ser35
2005-03-02 14:24
2005.03.13
Игнорирование невидимых компонентов


1-1109661973
Sancho
2005-03-01 10:26
2005.03.13
изменить настройки Locale


9-1103121746
D-Man
2004-12-15 17:42
2005.03.13
Генерация 2d карт


1-1109592246
}|{yk
2005-02-28 15:04
2005.03.13
После окончания генерации отчета Excel виснет


14-1109087267
r.o.o.t
2005-02-22 18:47
2005.03.13
АБАЛДЕТЬ!!!!!