На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: jack128, Rouse_, Krid
  
    > Как определить работает ли уже данное приложение , или это первая его копия?
      Для Delphi 1. Каждый экземпляр программы имеет ссылку на свою предыдущую копию - hPrevInst: hWnd. Ее можно проверить перед созданием приложения и при необходимости отреагировать соответствующим образом. Если запущена только одна копия, то эта ссылка равна нулю.
      Пример:


      procedure TForm1.FormCreate(Sender: TObject);
      begin
       {Проверяем есть ли указатель на предыдущую копию приложения}
       IF hPrevInst <> 0 THEN BEGIN
         {Если есть, то выдаем сообщение и выходим}
         MessageDlg('Программа уже запущена!', mtError, [mbOk], 0);
         Halt;
       END;
       {Иначе - ничего не делаем (не мешаем созданию формы)}
      end;


      P.S. Для выхода необходимо использовать Halt, а не Close, как хотелось бы, так как форма еще не создана и закрывать нечего.
      Есть и другой способ - по списку загруженных приложений




      procedure TForm1.FormCreate(Sender: TObject);
      VAR
      Wnd : hWnd;
      buff : ARRAY[0.. 127] OF Char;
      Begin
      Wnd := GetWindow(Handle, 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 StrPas (buff) = Application.Title THEN
        BEGIN
         MessageDlg('Приложение уже загружено', mtWarning, [mbOk], 0);
         Halt;
        END;
       END;
       Wnd := GetWindow (Wnd, gw_hWndNext);
      END;
      End;


      Еще один интересный способ для Win32. Дело в том, что можно в памяти создавать временные файлы. При перезагрузке они теряются, а так существуют. Кстати, этот метод можно использовать и для обмена информацией между вашими приложениями.

      Пример:


      program Project1;
      uses
       Windows, // Обязательно
       Forms,
       Unit1 in 'Unit1.pas' {Form1};

      {$R *.RES}
      Const
      MemFileSize = 1024;
      MemFileName = 'one_inst_demo_memfile';
      Var
      MemHnd : HWND;
      begin
       { Попытаемся создать файл в памяти }
       MemHnd := CreateFileMapping(HWND($FFFFFFFF),
                                   nil,
                                   PAGE_READWRITE,
                                   0,
                                   MemFileSize,
                                   MemFileName);
       { Если файл не существовал запускаем приложение }
       if GetLastError<>ERROR_ALREADY_EXISTS then
       begin
        Application.Initialize;
        Application.CreateForm(TForm1, Form1);
        Application.Run;
       end;
       CloseHandle(MemHnd);
      end.


      Часто при работе у пользователя может быть открыто 5-20 окон и сообщение о том, что программа уже запущено приводит к тому, что он вынужден полчаса искать ранее запущенную копию. Выход из положения - найдя копию программы активировать ее, для чего в последнем примере перед HALT необходимо добавить строку :
      SetForegroundWindow(Wnd);
      Например так:


      program Project0;
      uses
       Windows,  // !!!
       Forms,
       Unit0 in 'Unit0.pas' {Form1};

      var
       Handle1 : LongInt;
       Handle2 : LongInt;

      {$R *.RES}

      begin
       Application.Initialize;
       Handle1 := FindWindow('TForm1',nil);
       if handle1 = 0 then
         begin
           Application.CreateForm(TForm1, Form1);
           Application.Run;
         end
       else
         begin
           Handle2 := GetWindow(Handle1,GW_OWNER);
            //Чтоб заметили :)
           ShowWindow(Handle2,SW_HIDE); ShowWindow(Handle2,SW_RESTORE);
           SetForegroundWindow(Handle1); // Активизируем
         end;
      end.




      Комментарий от "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.Run;
          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);
                          inc(i);
                         end;
                        Application.Terminate;
                        Exit;
                       end;
                end;
             Wnd:=GetWindow(Wnd,gw_hWndNext);
            end;
          end;
      end.

      Если  программа  уже  запущена, управление будет передано существующей
      копии.

      >>> Прислать свои комментарии



      © Рассылка Мастеров Дельфи
      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
      0 пользователей:


      Рейтинг@Mail.ru
      [ Script execution time: 0,0156 ]   [ 16 queries used ]   [ Generated: 27.04.24, 21:12 GMT ]