Конференция "WinAPI" » Обработка сообщения на закрытие приложение [D6, WinXP]
 
  • leonidus (13.01.10 01:06) [0]
    Нужно реализовать корректную работу мой программы в случае если при ее запуске обнаружена ранее запущенная копия. В этом случае ранее запущенной копии нужно отправить сообщение на закрытие, а копия запущенная позже должна продолжать работать. Реализую поиск копии через атом, в который вместе с сигнатурой добавляю хендл запущенного приложения. Вторая копия находит сигнатуру, вычленяет хендл и отправляет сообщение wm_close_program, которое программа должна получить и закрыться осободив некие ресурсы.

    Делаю так:

    const
    wm_close_program=wm_User+500;

    type
     TForm1 = class(TForm)
     ...
     ...
     private
       { Private declarations }
     procedure WM_Close_Program_MSG(Var M : TMessage); message wm_Close_Program;
     public
       { Public declarations }
     end;

    ....
    ....

    procedure TForm1.WM_Close_Program_MSG(Var M : TMessage);
    begin
    GlobalDeleteAtom(m.WParam);
    application.Terminate;
    end;

    Суть проблемы в том, что если по хендлу, который я беру из атом отправить WM_CLOSE, то программа прекрасно закрывается, а вот сообщение wm_close_program она почему-то обработать не может. Я что не правильно его принимаю?
  • Игорь Шевченко © (13.01.10 03:14) [1]

    > а вот сообщение wm_close_program она почему-то обработать
    > не может.


    А если вставить после GlobalDeleteAtom(...)
    слово Close ?
  • Leonid Troyanovsky © (13.01.10 08:47) [2]

    > leonidus   (13.01.10 01:06)  

    > работать. Реализую поиск копии через атом

    Плохая идея. Если процесс будет терминирован,
    то атом будет жить  вплоть до логофа.

    Лучше взять memory mapped file.

    --
    Regards, LVT.
  • Leonid Troyanovsky © (13.01.10 09:02) [3]

    > leonidus   (13.01.10 01:06)  

    > с сигнатурой добавляю хендл запущенного приложения. Вторая
    ..
    > не может. Я что не правильно его принимаю?

    Если добавляется Application.Handle, то неправильно.

    --
    Regards, LVT.
  • leonidus (13.01.10 11:04) [4]
    Вот так ищу атом:

    var
    P: PChar;
    i,j: Word;
    handle:integer;
    begin
     GetMem(p, 256);
     for i := 0 to $FFFF do
     begin
       GlobalGetAtomName(i, p, 255);
       if StrPos(p, PChar('MyProgram_')) <> nil then
         begin
         handle:=strtoint(
         copy(p,ansipos('MyProgram_',p)+10,length(p))
         );
         PostMessage(handle, wm_Close_Program, i, 0);
         end;
     end;
     FreeMem(p);

    Вот так записываю атом:
    atom:='MyProgram_'+inttostr(application.Handle);
    GlobalAddAtom(pchar(atom));

    application.Handle то что нужно, ведь я могу по этому хендлу отправить wm_Close и программа закроется. на счет того, то атом в это случае будет жить вечно, с чего бы это? я отправляю сообщение PostMessage(handle, wm_Close_Program, i, 0); сожержащие номер найденного атома, а обработчик удалит его: GlobalDeleteAtom(m.WParam);. Другое дело, что обработчик то никак не может получить управление, вот и вопрос, почему?
  • Вариант (13.01.10 11:32) [5]

    > leonidus   (13.01.10 11:04) [4]


    > Другое дело, что обработчик то никак не может получить управление,
    >  вот и вопрос, почему?

    Form1.Handle <> Application.Handle

    И согласен с [2] - атомы не лучший вариант.
  • leonidus (13.01.10 11:42) [6]
    Ок, пусть будет MMF, но всеравно нужно разобраться с хендлом. Чтоже указывать в виде хендла приложения, чтобы можно было через PostMessage отправить собственное сообщение?
  • Вариант (13.01.10 11:53) [7]

    > leonidus   (13.01.10 11:42) [6]

    В твоем варианте речь не о приложении, а об окне.
    У тебя обработчик в твоем примере принадлежит классу TForm1, значит нужен WND окна, которое является экземпляром класса TForm1.

    А зачем посылать сообщение? И еще - а почему закрываем первую программу и оставляем работать вторую копию? (Я наоборот обычно делаю - проверяю, если прога уже запущена, то завершаю работу новой копии программы.)
  • Сергей М. © (13.01.10 11:55) [8]

    > Чтоже указывать в виде хендла приложения, чтобы можно было
    > через PostMessage отправить собственное сообщение?


    Ну ты же сам сказал


    > application.Handle то что нужно, ведь я могу по этому хендлу
    > отправить


    Application.Handle - это хэндл главного окна VCL-приложения.
    Оно невидимо, потому что его ширина и высота равны 0.
  • leonidus (13.01.10 13:18) [9]
    Разобрался, большое спасибо!
  • Pashka.cool (11.05.10 11:18) [10]
    Вот как я решал именно эту же проблему:
    В главном модуле своего приложения с заголовком "program" перед строкой Application.Initialization вставляю следующий код:
    var
     tmpStrList: TStringList;
     i: Integer;
     tmpAppName: String;
     flFound: Boolean;
    begin
     tmpStrList := TStringList.Create;
     try
       FillApplicationsList(tmpStrList);
       tmpAppName := ExtractFileName(Application.ExeName);
       for i := 0 to tmpStrList.Count - 1 do
       begin
         if AnsiUpperCase(tmpStrList[i]) = AnsiUpperCase(tmpAppName) then
         begin
           MessageDlg('Ця програма вже працює!', mtWarning, [mbOk], 0);
           Exit; // выход происходит до инициализации приложения
        end;  
     finally
       tmpStrList.Free;
     end;
     Application.Initialize;
     Application.CreateForm(TfrmTenderMain, frmTenderMain);
     Application.Run;
    end;
 
Конференция "WinAPI" » Обработка сообщения на закрытие приложение [D6, WinXP]
Есть новые Нет новых   [134431   +15][b:0][p:0]