Wiesz, to są materiały pisane między innymi pod XP, nie dziw się że nie działają na najnowszych systemach.
Rejestrowanie rozszerzeń nie zmieniło się od czasów WinXP praktycznie w ogóle.
Na potrzeby edytorów zawartości mojej gry, napisałem sobie funkcjonalność rejestrowania lokalizacji edytora (to samo co robią typowe instalatory) , a także rozszerzeń. Ważne! Rejestrowanie tych danych wymaga uprawnień administratora, bo dotyczy zapisu danych w kluczach HKEY_CLASSES_ROOT
i HKEY_LOCAL_MACHINE
, które są chronione przez system.
Rejestrowanie lokalizacji potrzebne jest do tego, aby program zawsze wiedział gdzie na dysku się znajduje. Bazowanie na Application.ExeName
to słabe rozwiązanie, bo jeśli się program uruchomi z dodatkowego toolbara na pasku zadań, to ścieżka aplikacji wskazywać będzie na pulpit, mimo że tam tej aplikacji nie ma. Zauważyłem to pierwszy raz na WinXP i tak samo jest na Win10. Rejestrowanie lokalizacji można olać, ale jeśli program trzyma dane (do odczytu) w plikach obok pliku wykonywalnego oraz korzysta ze ścieżek relatywnych, to mogą wystąpić błędy dostępu do tych plików (tak jak w przypadku ww. uruchomienia programu z toolbara).
Rejestrowanie rozszerzeń służy do dwóch celów. Po pierwsze, aby po uruchomieniu pliku o zadanym rozszerzeniu system otwierał go w moim edytorze. A po drugie, aby powłoka systemu wyświetlała określone przeze mnie ikonki dla konkretnych rozszerzeń. Nie tylko w eksploratorze plików, ale też w różnych menu kontekstowych, a nawet w cudzych programach, które ikonki ładują na podstawie ustawień systemowych (np. w 7-zip).
Pierwsza funkcja służy do zarejestrowania lokalizacji programu. Ja co prawda bazuję na Application.ExeName
, dlatego że nie robiłem instalatorów do edytorów — rejestrowanie tych rzeczy mam w oknie ustawień programu. To zwykle robi instalator, więc jeśli się to robi z poziomu aplikacji to lepiej się upewnić, że Application.ExeName
faktycznie zawiera prawidłową ścieżkę aplikacji.
function TEditorUtilsRegister.LocationRegister(): Integer;
var
Registry: TRegistry;
EditorPath: String;
begin
Result := EDITOR_ERROR_REGISTER_SUCCESS;
Registry := TRegistry.Create();
try
Registry.RootKey := HKEY_LOCAL_MACHINE;
if Registry.OpenKey('SOFTWARE\flowCRANE\Wtnc\Editor\Cursor', True) then
begin
EditorPath := ExtractFilePath(Application.ExeName);
EditorPath := IncludeTrailingPathDelimiter(EditorPath);
Registry.WriteString('', EditorPath);
end
else
Result := EDITOR_ERROR_REGISTER_FAILED;
finally
Registry.Free();
end;
end;
Ta funkcja otwiera rejestr, ustawia gałąź na HKEY_LOCAL_MACHINE
, a tworzy w nim klucz o ścieżce SOFTWARE\flowCRANE\Wtnc\Editor\Cursor
i otwiera go, a na koniec wpisuje ścieżkę programu do domyślnej wartości tego klucza (stąd pusty ciąg znaków jako nazwa wartości). Ścieżka powinna być absolutna i zakończona separatorem oraz nie zawierać nazwy pliku wykonywalnego.
Edytor przy starcie sprawdza istnienie tego klucza, pobiera ścieżkę z domyślnej wartości, dodaje do niej nazwę pliku wykonywalnego edytora i sprawdza czy plik wykonywalny istnieje pod taką ścieżką. Jeśli istnieje, to używa tej ścieżki do ustawienia working directory, tak aby edytor mógł używać ścieżek relatywnych w trakcie działania. A jeśli tych danych w rejestrze nie ma, to nie modyfikuje working directory. Jej kod wygląda tak:
function TEditorUtilsInstances.LoadLocation(): Boolean;
var
Registry: TRegistry;
EditorPath: String;
begin
Result := False;
Registry := TRegistry.Create();
try
Registry.RootKey := HKEY_LOCAL_MACHINE;
if Registry.OpenKeyReadOnly('SOFTWARE\flowCRANE\Wtnc\Editor\Cursor') then
begin
EditorPath := Registry.ReadString('');
EditorPath := IncludeTrailingPathDelimiter(EditorPath);
if FileExists(EditorPath + ExtractFileName(Application.ExeName)) then
if SetCurrentDir(EditorPath) then
begin
FLocation := EditorPath;
Result := True;
end;
end;
finally
Registry.Free();
end;
end;
Ścieżka pobierana z rejestru przez powyższą funkcję zapisywana jest w polu klasy i używana nie tylko do ustawienia working directory, ale też do zarejestrowania skojarzeń rozszerzeń plików. Tak jak niżej rejestruję rozszerzenie .cursor
, zawierających kursory przeznaczone dla mojej gry. Kod funkcji rejestrującej wygląda tak:
function TEditorUtilsRegister.AssociationRegister(): Integer;
var
Registry: TRegistry;
EditorExeName: String;
EditorPath: String = '';
EditorPathIcon: String;
EditorPathCommand: String;
begin
if not GetRegisteredLocation(EditorPath) then
exit(EDITOR_ERROR_REGISTER_FAILED);
EditorExeName := ExtractFileName(Application.ExeName);
EditorPathIcon := EditorPath + EditorExeName + ',0';
EditorPathCommand := '"' + EditorPath + EditorExeName + '" "%1"';
Result := EDITOR_ERROR_REGISTER_SUCCESS;
Registry := TRegistry.Create();
try
Registry.RootKey := HKEY_CLASSES_ROOT;
if Registry.OpenKey('.cursor', True) then
begin
Registry.WriteString('', 'Wtnc.Editor.Cursor');
Registry.CloseKey();
end
else
exit(EDITOR_ERROR_REGISTER_FAILED);
if Registry.OpenKey('Wtnc.Editor.Cursor', True) then
begin
Registry.WriteString('', 'Wtnc cursor file');
Registry.CloseKey();
end
else
exit(EDITOR_ERROR_REGISTER_FAILED);
if Registry.OpenKey('Wtnc.Editor.Cursor\DefaultIcon', True) then
begin
Registry.WriteString('', EditorPathIcon);
Registry.CloseKey();
end
else
exit(EDITOR_ERROR_REGISTER_FAILED);
if Registry.OpenKey('Wtnc.Editor.Cursor\shell\open\command', True) then
Registry.WriteString('', EditorPathCommand)
else
exit(EDITOR_ERROR_REGISTER_FAILED);
finally
Registry.Free();
end;
end;
Najpierw wywoływana jest funkcja GetRegisteredLocation
, która pobiera zarejestrowaną ścieżkę programu z rejestru. Potem otwiera gałąź HKEY_CLASSES_ROOT
, gdzie znajdują się dane skojarzeń i tam będzie zapisywać dane.
Pierwsze co należy zrobić to stworzyć klucz z nazwą rozszerzenia, poprzedzoną kropką — w powyższym przypadku klucz nosi nazwę .cursor
(rozszerzenie można sobie wymyślić dowolne). Ten klucz po stworzeniu należy otworzyć i do jego wartości domyślnej zapisać nazwę klucza-deskryptora, zawierającego informacje na temat rozszerzenia — u mnie jest to Wtnc.Editor.Cursor
(nazwa tego klucza może być dowolna). Po wszystkim zamykamy klucz rozszerzenia.
Następnie należy zarejestrować klucz-deskryptor, o takiej nazwie jaka została użyta w wartości domyślnej klucza rozszerzenia — czyli u mnie tworzony jest klucz o nazwie Wtnc.Editor.Cursor
. Po stworzeniu tego klucza, do jego wartości domyślnej wpisujemy ciąg znaków będący krótkim opisem czym jest plik z naszym rozszerzeniem (czyli z rozszerzeniem .cursor
). U mnie jest to plik z danymi kursora dla mojej gry, więc jako opis podałem Wtnc cursor file
.
Kolejnym krokiem jest zarejestrowanie ikonki dla plików. Należy stworzyć podklucz o nazwie DefaultIcon
i w jego wartości domyślnej podać ścieżkę pliku z ikonką. Tutaj jest spora dowolność, bo ścieżka może wskazywać bezpośrednio na plik .ico
, ale może też wskazywać na plik wykonywalny lub DLL, a jeśli tak, to dodatkowo można określić liczbowy indeks ikonki w zasobach exe/dll. U mnie ścieżka ikonki to pełna ścieżka pliku wykonywalnego edytora, zakończona sufiksem ,0
, co oznacza, że system ma użyć głównej ikony programu edytora jako ikonki plików z rozszerzeniem .cursor
.
Ostatnim krokiem (u mnie) jest dodanie skojarzenia rozszerzenia .cursor
z moim edytorem, tak aby otwarcie pliku .cursor
np. dwuklikiem w oknie eksploratora plików powodowało otwarcie mojego edytora i dostarczenie mu w parametrze uruchomieniowym ścieżki pliku kursora. Ścieżka otwartego pliku będzie dostępna w ParamStr(1)
.
Aby skojarzyć rozszerzenie z naszym programem, należy stworzyć podklucz shell\open\command
i w jego wartości domyślnej podać ciąg znaków komendy. Komenda to pełna ścieżka programu zakończona nazwą pliku wykonywalnego oraz z sufiksem "%1"
będącym rozkazem przekazania ścieżki pliku w parametrze uruchomieniowym. Warto jest ścieżkę programu objąć w cudzysłowy, bo może ona zawierać w sobie spacje. Pełna treść komendy powinna wyglądać w ten sposób:
"C:\Tutaj\Sciezka\Programu.exe" "%1"
Na koniec zamykamy rejestr i gotowe. Można do rejestru dodać znacznie więcej informacji, aby rozbudować sobie powłokę, np. dodać własne pozycje do systemowego menu kontekstowego dla plików z naszym rozszerzeniem (w eksploratorze plików czy na pulpicie), ale to zależy od wymagań. Ja potrzebowałem tego co wyżej i nic więcej.
Pliki moich kursorów w oknie eksploratora wyglądają tak: