Wielokrotne otwieranie

0

Dobry. Piszę programik odtwarzający muzykę. Gdy klikam jakiegoś (np) WAVEa w Explolerze, to mój prog sie uruchamia i go odtwarza. Co mam zrobić, aby po kliknięciu kolejnego utworu nie uruchamiał sie kolejny prog., ale muza szła w tym samym? Myślałem, aby po otwarciu aplikacji sprawdzić, czy już taka działa i jeżeli tak, to ją zamknąć. Robie tak:

procedure TMainForm.FormShow(...);
var
  hwd : THandle;
begin
  hwd := FindWindow('NazwaKlasyAplikacji', nil);
  SendMessage(hwd, WM_QUIT, 0, 0);
end;

Ale wtedy pod "hwd" wchodzi moja aktualna aplikacja i w efekcie program zabija sam siebie, a nie ten drugi egzemplarz. Co zrobić? Jest jakaś inna, lepsza metoda rozwiązania problemu? Jakieś "przekierowanie parametru" programu?

0

wykonaj to sprawdzenie zanim utworzysz okno. OnCreate jest wykonywane PO utworzeniu okna.

0

<ściana>

No jasne. Myślałem o tym, ale nie wiedziałem, że OnCreate jest PO. Dzięki! :D

0

do tego celu można uŻyć Mutex'ów (CreateMutex, OpenMutex, ReleaseMutex)

0

Robie coś podobnego i mam podobny problem ;).

Z zamknięciem kopii programu już sobie poradziłem, ale nie wiem, jak teraz przekazać ten plik do otwarcia tej "pierwotnej" kopii programu...

0

Osobiście się czymś takim nie zajmowałem, ale wydaje i się, że powinno zadziałać zastosowanie komunikatów.

Program przy otwieraniu wpisuje ścieżkę pliku do rejestru, a potem wysyła komunikat. Jeśli jest już otwarta inna instancja tego programu to się zamyka. Ten fragment już macie. Inne instancje (domyślnie ta jedna już otwarta) jak odbirą ten komunikat to pobierają z rejestru ścieżkę do nowego pliku i dodają ją do listy.

Tak jak pisałem, nie bawiłem się jeszcze w ten sposób, ale wydaje mi się że to ma prawo działać.

0

Nie miałem czasu jeszcze pobawić sie z Mutexami, ale wysłanie komunikatu zabijającego w Project Source, przed instrukcjami "Application.Initialize, CreateForm, Run" nie działa. Ani też w bloku Initialization. Program cały czas pobiera swój własny uchwyt.

W głowie zalęgła mi się co prawda myśl jak rozwiązać to jeszcze "prosciej", ale odpowiedź jest zawsze mile widziana.

0
  han:= OpenMutex(MUTEX_ALL_ACCESS, true, 'Mutex jakis sobie tam');
  if han = 0 then begin
     han:= CreateMutex(nil, true, 'Mutex jakis sobie tam');
     if han = ERROR_ALREADY_EXISTS then begin
        MessageBox(0, 'Blad', '', 0);
        Exit;
     end;

     Application.Initialize;
     Application.CreateForm(TForm1, Form1);
     Application.Run;

     ReleaseMutex(han);
     CloseHandle(han);
  end else begin
     MessageBox(0, 'Inna aplikacja ORT!!!! tego samego mutexa', '', 0);
  end;
0

Cześć
Przykładowy kod... możesz go przerobić na swoje potrzeby - blokuje uruchomienie tego samego programu i może wykonać Twoje instrukcje np. zmiana ścieżki do odtwarzanego pliku.

{========== Szukanie uchwytu okna wg. podanego tytułu okna ==========}
Function EnumCallBack(H:HWND; L:LPARAM):BOOL;stdcall;
var
 x :Integer;
 a :array of Char;
 nazwa :String;
Begin
 nazwa:= 'Moj Odtwarzacz';                   //nazwa okna 
 EnumCallBack:= True;
 x:= GetWindowTextLength(H) + 1;
 SetLength(a,x);
 GetWindowText(H,PChar(a),x);
 if Pos(nazwa,PChar(a)) > 0 then
 begin
   HWND(Pointer(L)^):= H;
   ShowWindow(h,SW_SHOW);        //pokazuje okno
   SetForegroundWindow(h);          //wydobywa okno na wierzch
   //W TYM MIEJSCU PODSTAW INSTRUKCJE CO MA WYKONAĆ 
   
   
   EnumCallBack:= False;
 end;
 SetLength(a,0);
End; 
//////////// Instrukcje do wykonania podczas załadowania programu /////////////
Var
 UchwytDC   :HDC;
 UchwytOkna :HWND;
 nazwa      :String;
INITIALIZATION
 //Blokada przed ponownym uruchomieniem programu...
 nazwa:= ExtractFileName(Application.ExeName);       //wyciąga nazwę ze ścieżki
 UchwytDC:= CreateFileMapping(THANDLE($FFFFFFFF),nil,PAGE_READONLY,0,32,PChar(nazwa));
 if GetLastError = ERROR_ALREADY_EXISTS then
 begin
   UchwytOkna:= 0;
   EnumWindows(@EnumCallBack,LPARAM(@UchwytOkna));  //do proc. szukania uchwytu okna
   CloseHandle(UchwytDC);
   CloseHandle(UchwytOkna);
   //Application.Terminate; //przy tej instrukcji mrugnie drugi guzik programu
   HALT;          //używając instrukcji zatrzymania nie mamy żadnych "efektów"
 end; 
{*********************************************************************}
END.
0

Dzięki. Stary kot zobaczy, co da się z tego zrobić...

0

To umieść w pliku *.dpr

var
  han, FileMapping: THandle;
  t: String;

begin
  han:= OpenMutex(MUTEX_ALL_ACCESS, true, 'Mutex jakis sobie tam');
  if han = 0 then begin
     han:= CreateMutex(nil, true, 'Mutex jakis sobie tam');
     if han = ERROR_ALREADY_EXISTS then begin
        MessageBox(0, '', '', 0);
        CloseHandle(han);
        Exit;
     end;
     FileMapping:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, MemoryFileSize, MemoryFileName);
     if FileMapping <> 0 then begin
        ViewOfFile:= MapViewOfFile(FileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
     end;

     Application.Initialize;
     Application.CreateForm(TForm1, Form1);
     Application.Run;

     ReleaseMutex(han);
     CloseHandle(han);
     UnmapViewOfFile(ViewOfFile);
     CloseHandle(FileMapping);
  end else begin
     //MessageBox(0, 'Inna aplikacja urzywa tego samego mutexa', '', 0);
     FileMapping:= OpenFileMapping(FILE_MAP_WRITE, True, MemoryFileName);
     if FileMapping = 0 then
        Exit;
     ViewOfFile:= MapViewOfFile(FileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
     t:= 'Te dane zostaną przekazane do aplikacji która jest już uruchomiona';
     Move(PChar(t)^, ViewOfFile^, Length(t));
     UnmapViewOfFile(ViewOfFile);
     CloseHandle(FileMapping);
     PostMessage(HWND_BROADCAST, WM_MESSAGE, 0, 0);
     CloseHandle(han);
  end;

a to przed implementation w module z definicją głównego okna aplikacji

const
  MemoryFileSize = 4 * 1024;
  MemoryFileName = 'D9287E19-6F9E-45fa-897C-D392F73A0F2F';
var
  WM_MESSAGE: Integer = WM_USER + 19;

var
  ViewOfFile: Pointer;

w tym samum module dopisz

  Application.OnMessage:= FF;
.
.
.
procedure TForm1.FF(var Msg: TMsg; var Handled: Boolean);
var
  i: String;
begin
  if MSg.message = WM_MESSAGE then begin
     i:= StrPas(PChar(ViewOfFile));
     Memo1.Lines.Add(i);
  end;
end;

oraz

initialization
   WM_MESSAGE:= RegisterWindowMessage('{70BCC26C-CBF2-4364-B988-90F46C3D269C}');
0

wow. dzięki :]

0

czemu po uzyciu tego kodu otwiera mi się plik aż 16 razy?

1 użytkowników online, w tym zalogowanych: 0, gości: 1