Otwieranie jednej instancji programu zewnętrznego (ShellExecute)

Otwieranie jednej instancji programu zewnętrznego (ShellExecute)
vroobell13
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 11 lat
  • Postów:1
0

Program obsługuje bazę efektów dźwiekowych.
Kiedy użytkownik chce przesłuchać wybrany efekt, klika pozycję na liście. Program sam określa, który program ma dany dźwięk otworzyć. Problem polega na tym, że kiedy uruchamiam wybrany program poleceniem:

Kopiuj
exename:=VlcAppPath; // ścieżka do aplikacji odwarzającej; tu: VLC Media player
Parms:=Filename;
res:=ShellExecute(MainF.handle,'open',PChar(exename+''),PChar('"'+Parms+'"'),'',sw_ShowNormal);

za każdym uruchomieniem otwiera sie nowe okno odtwarzacza. Niekiedy daje to niezły efekt mieszania dźwięku, ale w podstawowym trybie wolałbym, żeby w chwili kolejnego wywołania program odtwarzający przeerywał odtwarzanie bieżącego dźwięku i zaczynał własnie kliknięty (w tej samej instancji odtwarzacza). Dokładnie tak, jak to robi eksplorator Windows, kiedy nie czekając na koniec poprzedniego dźwięku kliknę kolejny plik *.flv;
Próbowałem różnych parametrów wywołania (nShowCmd), ale żadne nie powoduje opisanego dzialania.
Przeszukałem 4programerz.net i delphi.about.com (wiele sie przy tym nauczyłem), ale nie napotkałem odpowiedzi. Może ktoś cos wie na ten temat?


aps
vroobell13
Panowie.... Nie wszyscy naraz!!! Nie spodziewałem się tak błyskawicznej reakcji i takiego zalewu informacji. Nigdy dotąd nie korzystałem z forów internetowych dla rozwiązania napotkanych problemów, toteż jestem zaszokowany... Serdecznie wszystkim dziękuję i biorę się za wykorzystywanie tego wszystkiego w praktyce
hzmzp
  • Rejestracja:ponad 11 lat
  • Ostatnio:25 minut
  • Postów:620
0

Poczytaj o komunikatach...
To dość proste, bierzesz podczas uruchamiania appki sprawdzasz czy nie ma już uruchomionej jgko kopii jeżeli jest to wysyłasz do niej ścieżkę do pliku który chcesz otworzyć i zamykasz tą instancję, a tamta odbiera wiadomość i wykonuje stosowne akcje.

olesio
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
0

Jeżeli dobrze zrozumiałem, to kiedy chcesz osiągnąc efekt jak dla Exploratora. To należało by wywoływać plik, a nie program i parametr. O ile w ogóle VLC Player działa ok. Ponieważ nawet kiedy w WinAMPie ustawiłem opcję aby uruchamiał się w wielu instancjach i zrobiłem taki kod programu, jak widać poniżej. To WinAMP nie wywołał mi się dwa razy. A klikałem przyciski naprzemiennie. Może jeszcze jakieś dodatkowe wpisy akurat dla niego w rejestrze o tym decydują, ale wątpie. To ważne jak program chyba jest stworzony. Na przykład czy nie tworzy Mutex i nie obsługuje nowych parametrów przy podaniu kiedy jest już uruchomiony.

Kopiuj
//...
procedure TForm1.Button1Click(Sender : TObject);
begin
  ShellExecute(Handle, 'open', PChar('C:\PROGRAM FILES\WINAMP\winamp.exe'), PChar('"' + 'C:\PROGRAMY\MP3\Weekend - Ona Tanczy Dla Mnie.mp3' + '"'), '', SW_SHOWNORMAL);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ShellExecute(Handle, 'open', PChar('C:\PROGRAM FILES\WINAMP\winamp.exe'), PChar('"' + 'C:\PROGRAMY\MP3\Sobota & Weekend - Ona Tanczy Dla Mnie (2sty Blend).mp3' + '"'), '', SW_SHOWNORMAL);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ShellExecute(Handle, 'open', PChar('"' + 'C:\PROGRAMY\MP3\Weekend - Ona Tanczy Dla Mnie.mp3' + '"'), '', '', SW_SHOWNORMAL);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  ShellExecute(Handle, 'open', PChar('"' + 'C:\PROGRAMY\MP3\Sobota & Weekend - Ona Tanczy Dla Mnie (2sty Blend).mp3' + '"'), '', '', SW_SHOWNORMAL);
end;

Jeżeli jednak Explorator zachowuje się ok to myślę, że powinno pomóc wywołanie pliku. Ponieważ kiedy robisz dwuklik na pliku, to o ile się orientuje robisz właśnie tak jakbyś wywoływał sam plik jako program, a parametr pusty. Ewentualnie zobacz w Rejestrze czy wywołanie plików .flv przez VLC nie odbywa się z jakimis dodatkowymi parametrami i tym podobne. Jeżeli to i reinstall nie pomoże to nie wiem jak można by jeszcze kombinować. Nie mam zamiaru instalować VLC na chwile i psuć sobie skojarzenia dla plików filmów. Natomiast przedwczesne jest raczej "wytaczanie takich dział" jak próba napisania wrappera dll (o ile taki da się łatwo napisac, bo VLC obsluguje jakąś udokumentowaną dllkę systemową przez małą ilośc eksportów), co jest moją jedną z moich ulubionych metod i w miarę łatwych do zaimplementowania. Jeżeli oczywiście chcemy łatwo ingerować w zachowanie kodu oryginalnego programu bez jego ręcznego patchowania albo inwazyjnego injectowania dllek. Wtedy takim wrapperem można by spróbować najprościej tworzyć Mutex o unikalnej nazwie. Tylko kwestia, co zrobić jeżeli on by istniał. Jak przekazać nowy plik do VLC. Chyba tylko symulacją komunikatu o przeciąganiu pliku na okno, ewentualnie mechanizmem DDE jeżeli jest obsługiwany i udokumentowany dla tego playera. W ostateczności można szukać pomocy w supporcie VLC.


Pozdrawiam.
edytowany 2x, ostatnio: olesio
KA
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Gorlice
0

Obawiam się że takiego czegoś nie uzyskasz gdyż to zależy w jaki sposób dany program który ma odtwarzać jest napisany czyli to program musi pozwalać się otworzyć tylko w jednej instancji i odtwarzać podany jako parametr plik (jeżeli jest już otarty to przerywać odtwarzanie poprzedniego a odtwarzać ten nowy). Jeżeli dany odtwarzacz ma udostępnia API (jak np Winamp) to mógłbyś spróbować sterować nim poprzez to API (oczywiście o ile jest taka możliwość bo nie zajmowałem się w zabawy z API Winampa ale raczej powinno się dać).


Nie odpowiadam na PW w sprawie pomocy programistycznej.
Pytania zadawaj na forum, bo:
od tego ono jest ;) | celowo nie zawracasz gitary | przeczyta to więcej osób a więc większe szanse że ktoś pomoże.
Zobacz pozostały 1 komentarz
olesio
@marogo: mowa i tak o VLC, a sterowanie jeżeli chodzi o zapodawanie nazw plików to z komunikatów nie wiem czy może się odbywać. Raczej ewentualnie przez zasymulowanie przerzucenia plików komunikatem WM_DROPFILES, ale nigdy się tak nie bawiłem. Nie miałem potrzeby. A i nie wiem czy WM_DROPFILES da się łatwo zasymulować.
MA
Dla Winampa, nie działa, po podstawieniu za "Wnd" uchwytu okna Winampa lub jego playlist-y.
olesio
@marogo: zobacz EDIT #3 w moim, ostatnim póki co postcie, bo jednak powyższy kod nie działał dla więcej niż jednego pliku pomimo zmiany na PostMessage. Dopiero elegancko działa kod z: http://www.delphi-zone.com/2010/02/how-to-send-data-to-another-program-by-auto-dragdrop - podejrzewam, że to kwestia złego tworzenia danych do wysłania we wcześniejszym kodzie. Jak dodawałem do długości Run + 1, to działalo ale potrafiło za pierwszym razem wieszać WinAMP. Teraz po wielu testach jest ok.
MA
  • Rejestracja:ponad 16 lat
  • Ostatnio:18 dni
0

Sprawdź, czy uruchamiany player ma w ustawieniach (włączoną) opcję w stylu "Uruchamiaj tylko jedną instancję" lub wyłączoną opcję w stylu "Pozwól na wiele instancji" lub też poszukaj w helpie playera, czy można go uruchomić z określonym parametrem, który pozwala mu działać tylko w jednej instancji.

olesio
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
0

Propozycja @hzmzp jest według mnie za bardzo inwazyjna, bo zamykamy i otwieramy ponownie program co może potrwać. Natomiast @kAzek napisał o WinAMPie albo sugerując się jego działaniem albo moim kodem. Natomiast pytanie jest o VLC. Który może faktycznie działać inaczej. Chociaż jeżeli przez dwuklik z exploratora jest ok. To podejrzewał bym albo wywoływanie z odpowiednimi parametrami poza nazwą pliku. Albo inną domyślną czynnośc niż open. Albo obsługę DDE. Niestety w nowszych Windowsach o ile się orientuje skopano względem XP trochę ustawianie i podgląd skojarzonych rozszerzeń. Także takie operacje jak podgląd albo zmiana domyślnej czynności i innych ustawień najlepiej dokonać w Rejetrze - konkretnie dla HKEY_CLASSES_ROOT\.FLV, a później dla klucza, który jest w nazwie domyślnej oczywiście.

EDIT: o - poniżej elegancki kod na zasymulowanie przerzucenia plików. Trzeba sobie tylko ustalić uchawyt okna VLC za pewne. Bo chyba obsługuje ono Drag and Drog. To może będzie to jakieś rozwiązanie: http://www.vbforums.com/showthread.php?632732-Simulate-Drop-Files-with-SendMessage-WM_DROPFILES o ile się nie uda inaczej.

EDIT #2: zgodnie z informacją zawartą w treści wątku na: http://us.generation-nt.com/an[...]les-message-help-57315072.html - powyższy kod na symulowanie WM_DROPFILES zadziała, tylko trzeba użyć PostMessage zamiast SendMessage.

EDIT #3: powyższe kombinacje jednak źle działają dla więcej niż jednego pliku, a dodawanie do długości zmiennej Run nawet +1 powoduje obsługe ok po pierwszym uruchomieniu WinAMP'a. Nie analizowałem zmian, ale ten kod, który pochodzi ze strony: http://www.delphi-zone.com/2010/02/how-to-send-data-to-another-program-by-auto-dragdrop sprawdza się znakomicie, a i ma ten plus, że jest już przyszłościowo pod kątem WinAMP ;) Oczywiście nie problem prxerobić go na skorzystanie z TStringList i VCL. Poniżej przykład dla szybkich testów. Zakładam, że takie pliki jak ja macie w media. Przynajmniej pod siódemką takowe są.

Kopiuj
//...
uses
  ShellApi;

function MakeDrop(const FileNames : array of string) : THandle;
var
  P : PChar;
  Data : PDragInfoA;
  I, Size : Integer;
begin
  Size := SizeOf(TDragInfoA) + 1;
  for I := 0 to High(FileNames) do
  begin
    Inc(Size, Length(FileNames[I]) + 1);
  end;
  Result := GlobalAlloc(GHND or GMEM_SHARE, Size);
  if Result <> 0 then
  begin
    Data := GlobalLock(Result);
    if Data <> nil then
      try
        Data.uSize := SizeOf(TDragInfoA);
        P := PChar(@Data.grfKeyState) + 4;
        Data.lpFileList := P;
        for I := 0 to High(FileNames) do
        begin
          Size := Length(FileNames[I]);
          Move(Pointer(FileNames[I])^, P^, Size);
          Inc(P, Size + 1);
        end;
      finally
        GlobalUnlock(Result);
      end
    else
    begin
      GlobalFree(Result);
      Result := 0;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender : TObject);
begin
  Application.Title := Caption;
end;

procedure TForm1.Button1Click(Sender : TObject);
var
  H : HWND;
  Drop : HDrop;
begin
  H := FindWindow('Winamp v1.x', nil);
  if H > 0 then
  begin
    Drop := MakeDrop
      (['C:\WINDOWS\MEDIA\flourish.mid',
      'C:\WINDOWS\MEDIA\town.mid',
        'C:\WINDOWS\MEDIA\chord.wav']);
    if Drop <> 0 then
    begin
      PostMessage(H, WM_DropFiles, Drop, 0);
    end;
    GlobalFree(Drop);
  end;
end;

Pozdrawiam.
edytowany 4x, ostatnio: olesio
MA
Na Winampie działa :)
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 13 godzin
0

Program obsługuje bazę efektów dźwiekowych.
Kiedy użytkownik chce przesłuchać wybrany efekt, klika pozycję na liście.
No ok, ale po co do tego zewnętrzny program przez ShellExecute, zamiast odtworzyć dźwięk wewnątrz programu, dowolnym działającym sposobem?

olesio
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
0

@Azarien: jakby to był typowy format i chodzilo tylko o dźwięk to wiadomo, że chyba najprościej o najlepiej było by posiłkować się bass.dll. Ja jednak kiedy widzę flv i chęć użycia VLC Playera, to podejrzewam że może chodzić również o wyświetlenie ruchomego obrazu. A z pokazywaniem video poza TMediaPlayer i avi osobiście nie mam doświadczenia w Delphi. Wydaje mi się też, że chyba nie ma łatwego do ogarnięcia rozwiązania w postaci dllka, wyświetlenie na oknie o podanym handle i wygodna nawigacja. Czyli bez kombinowania z kodekami i tym podobnymi. Co nie oznacza, że używanie zewnętrznego programu do tego co można spróbować zrobić samodzielnie jest rozwiązaniem godnym polecenia. Bo można inaczej, także jeżeli pytającemy na pewno chodzi tylko o dźwięk to najlepiej przekonwertować flv na mp3, ponazywać sensownie. I albo wrzucić do podkatalogu jako dane i ogarnąć bass.dll albo ewentualnie jeżeli chcemy mieć wszystko w postaci jednego exeka to polecam bass.dll i moduł dllloader.pas z funkcją FindExport. Wpakować wszystko w zasób, ewentualnie mp3ki też jako zasoby tylko wczytywane i zapisywane po ID odpowiednim konstruktorem dla TResourceSream (czyli w pliku *.rc # i liczba jako nazwa zasobu). Wczytywanie po ID zgodnie z tym co piszą w helpie do Delphi, ma znaczenie nie tyle jeżeli chodzi o wielkość sumaryczną zasobów co ewentualną ich ilośc ponad kilkaset sztuk w jednym exeku. Oczywiście można jeszcze kombinować z dllką jako pliko zasobem zewnętrznym. Ale jeśli chcemy sobie zrobić ładny i zgrabny program wszystko w jednym to faktycznie chyba tak najlepiej. Anyway, już pytający otrzymał w tym wątku tyle konkretnych rad, że na pewno spokojnie można siąść i zakować coś porządnego bez "męczenia" VLC do dźwięku :)


Pozdrawiam.
edytowany 1x, ostatnio: olesio
Azarien
ja bym użył po prostu DirectShow, obsłuży wszystkie kodeki i formaty zainstalowane w systemie. podczepienie wideo pod uchwyt okna też jest proste. nie używałem co prawda DShow nigdy pod Delphi.
MA
  • Rejestracja:ponad 16 lat
  • Ostatnio:18 dni
0

W pomocy programu VLC media player-a: https://wiki.videolan.org/VLC_command-line_help jest opisany parametr dotyczący uruchamiania pojedynczej instancji: --one-instance , co przekłada się na takie wywołanie ShellExecute:

Kopiuj
ShellExecute(MainF.handle, 'open', PChar(exename), PChar('--one-instance "'+Parms+'"'),'',sw_ShowNormal);
MA
Jeśli pliki multimedialne o określonych rozszerzeniach byłyby skojarzone z różnymi playerami, to przed otwarciem danego typu pliku należałoby sprawdzać w rejestrach (HKEY_CLASSES_ROOT) z jakim playerem jest skojarzony i odpowiednio podawać parametr pozwalający na uruchomienie tylko jednej instancji. Niestety wiąże się to z tym, że program musiałby mieć taką tablicę (bądź mini bazę) przechowującą nazwę tego parametru dla wszystkich popularnych playerów, które oczywiście maja możliwość odpalenia tylko w pojedynczej instancji.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)