Proponuję wykorzystać rozszerzenie powłoki ContextMenuHandler, w połączeniu z Mutexem i WMCopyData. Co prawda też mamy tu do czynienia z mutexem i przekazywaniem danych przez komunikaty, jednak jest to rozwiązanie na tyle odmienne, że może warto zwrócić na nie uwagę.
Rozszerzenie powłoki jest specjalną biblioteką DLL, którą trzeba zainstalować w systemie poprzez odpowiednie wywołanie zaimplementowanej w niej funkcji DllRegisterServer lub np. za pomocą systemowego regsvr32.exe. W bibioltece takiej można dodawać własne polecenia do menu kontekstowego plików i/lub folderów. Jeśli użytkownik zaznaczy w Eksploratorze wiele elementów i z menu kontekstowego wybierze dodane przez nas polecenie, do odpowiedniej funkcji w tej bibliotece zostaną przekazane nazwy (ścieżki) wszystkich zaznaczonych plików/folderów. Teraz wystarczy tylko uruchomić właściwą aplikację i przekazać do niej listę tych plików (np. zapisaną w pliku tekstowym). Różnica pomiędzy wywołaniem polecenia z menu kontekstowego dodanego za pomocą rozszerzenia ContextMenuHandler oraz metody standardowej (...shell\open\command itd.) polega na tym, że w pierwszym przypadku lista wszystkich zaznaczonych plików zostanie przekazana do odpowiedniej funkcji w bibliotece DLL (funkcja ta zostanie wywołana tylko jeden raz), zaś w drugim przypadku aplikacja podana w shell\open\command zostanie uruchomiona tyle razy, ile plików/folderów było zaznaczonych w Eksploratorze, a do każdej instancji przekazana zostanie ścieżka do kolejnego zaznaczonego pliku/folderu.
Rozszerzenia powłoki są często wykorzystywane przez aplikacje operujące na plikach; chociażby w archiwizatorze WinRAR. Program ten instaluje w systemie rozszerzenia powłoki (ContextMenuHandler oraz DragDropHandler) zaimplementowane w bibliotece RarExt.dll. Biblioteka ta dodaje do menu kontekstowego polecenia "Dodaj do archiwum", "Dodaj do archiwum i wyślij..." itp. Po wybraniu jednego z tych poleceń, w katalogu z plikami tymczasowymi tworzony jest plik, którego nazwa rozpoczyna się od Rar$, a końcówka jest generowana losowo (chyba) (np. Rar$LS41.29734). Jest to zwykły plik tekstowy, w którym zapisana jest lista plików/folderów zaznaczonych przez użytkownika w Eksploratorze. Następnie RarExt.dll uruchamia właściwy program, tj. WinRARa, i przekazuje do niego nazwę pliku z zapisaną listą. WinRAR wczytuje z tego pliku nazwy zaznaczonych plików, po czym kasuje plik tekstowy Rar$...
Jeżeli jesteś zainteresowany takim rozwiązaniem, przejrzyj źródła przykładowego projektu MyShellExtension, które są dostępne online na stronie http://www.pazera-download.com/_pub/delphi/MyShellExtension_src.html. Ilość kodu jest dosyć duża, dlatego nie mogę podać go w poście.
Skompilowany projekt z wszystkimi plikami źródłowymi: http://www.pazera-download.com/_pub/delphi/MyShellExtension.zip (354 KB).
Krótki opis działania i instrukcja oobsługi:
-
Uruchom program MyApp.exe i kliknij przycisk "Zarejestruj MyShellExtension.dll".
MyApp.exe zarejestruje wówczas w systemie rozszerzenie powłoki ContextMenuHandler zaimplementowane w bibliotece MyShellExtension.dll (procedura RegisterShellExtension).
-
Zaznacz kilka plików w Eksploratorze, kliknij prawy klawisz myszy i wybierz polecenie "MyShellExtension test".
Eksplorator przekaże wtedy listę wszystkich zaznaczonych plików do naszego DLLa, który zapisze ją w systemowym katalogu przeznaczonym na pliki tymczasowe w pliku tekstowym, którego nazwa będzie się rozpoczynać od "MyShellExtension_", a końcówkę będzie stanowić ciąg liczb szesnastkowych generowanych losowo i rozszerzenie ".txt". Następnie uruchomiana jest właściwa aplikacja (MyApp.exe), w parametrze 1-szym zostanie do niej przekazany łańcuch "AddFiles", a w 2-gim ścieżka do utworzonego przed chwilą pliku tekstowego z listą plików zaznaczonych w Eksploratorze. W tym miejscu należy zaznaczyć, że nasz DLL musi znać ścieżkę do pliku MyApp.exe (w przykładzie tym wykorzystałem rejestr). Trzeba pamiętać, że MyShellExtension.dll nie jest samodzielną aplikacją, jedynie "dodatkiem" do Eksploratora i nawet jeśli umieścimy naszego DLLa i plik MyApp.exe w jednym katalogu, po wywołaniu ExtractFileDir(ParamStr(0)) wewnątrz DLLa, nie otrzymamy ścieżki do katalogu, w którym znajdują się oba pliki, tylko do katalogu z Eksploratorem Windows (z plikiem explorer.exe).
-
Uruchamiana jest aplikacja MyApp.exe, która - wykorzystując CreateMutex - sprawdza czy jest już uruchomiona instancja programu. Jeśli nie, działanie MyApp.exe jest kontynuowane, jeśli jednak aplikacja została już wcześniej uruchomiona, wysyłany zostaje do niej komunikat WM_COPYDATA, w którym przekazywana jest nazwa pliku tekstowego z listą plików zaznaczonych w Eksploratorze, po czym instancja wysyłająca komunikat kończy działanie. MyApp.exe, po odebraniu takiego komunikatu, wczytuje listę zaznaczonych plików z pliku tesktowego, wypisuje nazwy tych plików w Memo1, a następnie - podobnie jak WinRAR - usuwa z katalogu tymczasowego już niepotrzebny plik tekstowy.
Zainteresowanym polecam także analizę kodów źródłowych programów demonstracyjnych dołączanych do Delphi: ContextM, CopyHk i TRegSvr.