Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.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 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.039 c
4-1107244363
VsInLg
2005-02-01 10:52
2005.03.13
CreateThread и BeginThread


1-1109370824
Германн
2005-02-26 01:33
2005.03.13
EInOutError - Прав ли я, что оно "малополезно"?


9-1103402156
Goldseeker
2004-12-18 23:35
2005.03.13
Опять столкновения


4-1107077574
Максим
2005-01-30 12:32
2005.03.13
Выключение компьютера


3-1107277551
UVV
2005-02-01 20:05
2005.03.13
DataSource.DataSet.IsEmpty





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский