Entwickler-Ecke

Open Source Units - TFileTypeRegistration (Dateityp registrieren)


Delete - Fr 02.07.04 22:28
Titel: TFileTypeRegistration (Dateityp registrieren)
Ich lege gleich noch einen nach -

Es gab ja schon einige Beiträge zum Thema "Wie registriere ich meinen eigenen Dateityp?" Die meisten Funktionen waren mir persönlich allerdings nicht detailliert genug. Aus dem Grund habe ich eine eigene Klasse namens TFileTypeRegistration entworfen, die sich natürlich hauptsächlich an meinen Wünschen orientiert, aber evtl. auch für andere von Interesse ist.

Im Anhang gibt es die Units und ein Beispiel. Nun ist der Quellcode zwar kommentiert und enthält auch ein paar Beispiele. Aber trotzdem möchte ich kurz die Vorteile aufzählen, die es IMHO gibt -

Die meisten Funktionen registrieren einen Dateityp mit einer einzigen Aktion (wie open o.ä.). Sollen mehrere Aktionen für den Typ registriert werden, muss die Funktion u.U. mehrfach aufgerufen werden. Dabei sind immer wieder die gleichen Parameter zu übergeben, was IMHO die Gefahr von Tipp- o.ä. Fehlern erhöht. Unter Umständen schreibt man also in den falschen Schlüssel.
Das kann bei der o.g. Klasse nicht passieren, weil hier die wichtigsten Eigenschaften einmal beim Registrieren des Typs gesetzt und dann intern benutzt werden. Daher sieht ein Aufruf so aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
ftr := TFileTypeRegistration.Create;
try
  if(ftr.RegisterType('.foo','FooFile','FOO-File')) then
  begin
    ftr.AddHandler('open','notepad.exe "%1"','Öffnen');
    ftr.AddHandler('print','notepad.exe /p "%1"');
    // usw.
  end;
finally
  ftr.Free;
end;


Dann kann man auch den Standardhandler setzen; das ist der Eintrag, der im Kontextmenü fett gedruckt wird, und der bei einem Doppelklick auf die entsprechende Datei ausgeführt wird. Die Funktion "SetDefaultHandler" benutzt dabei den zuletzt benutzten Handler. Im o.g. Beispiel wäre das print.
Da die Funktion überladen ist, kann man den gewünschten Handler aber auch selbst wählen:

Delphi-Quelltext
1:
    ftr.SetDefaultHandler('open');                    


Und man kann dafür sorgen, dass sich der eigene Typ auch bequem über das Menü "Neu" anlegen lässt. Das kennt man bspw. von Textdateien (Rechtsklick in einen freien Bereich -> Neu -> Textdatei). Allerdings darf die Beschreibung des Dateityps kein Leerzeichen aufweisen, und sie darf nicht leer sein. Es muss also beim Registrieren zwingend eine Beschreibung angegeben werden, weil diese die Referenz für den Dateinamen bildet.
Der entsprechende Befehl der Klasse lautet

Delphi-Quelltext
1:
    ftr.AddNewFileSupport;                    

Mit "RemoveNewFileSupport" lässt sich diese Fähigkeit zu einem späteren Zeitpunkt wieder aufheben, ohne dass dafür der Dateityp entfernt und neu registriert werden muss.

Das war übrigens ein weiterer Kritikpunkt, den ich bei diversen anderen Lösungen hatte. Man konnte immer nur den kompletten Typ entfernen, nie nur einzelne Handler. Mit der o.g. Klasse geht es aber:

Delphi-Quelltext
1:
2:
  if(ftr.GetInternalKey('.foo') <> ''then
    ftr.DeleteHandler('print');

Die Funktion "GetInternalKey" liefert hier den internen Schlüssel zurück, auf den ".foo" zeigt. Das Rückgabeergebnis interessiert in dem Fall aber nicht, weil auch die Eigenschaft "FInternalName" gesetzt wird, die ihrerseits von "DeleteHandler" verwendet wird. Auf die Weise besteht also IMHO nicht die Gefahr, dass man in einem falschen Schlüssel löscht.

Um den kompletten Typ zu entfernen, benutzt man

Delphi-Quelltext
1:
  ftr.UnregisterType('.foo');                    



Noch etwas, das bei anderen, mir bekannten Lösungen nicht möglich war, ist das "Verlinken" mit bereits existierenden Typen. Angenommen der ".foo"-Typ ist auch bloß eine Textdatei, dann könnte ich doch dafür sorgen, dass der Typ intern mit den Textdateien verknüpft wird.
Dazu muss ich lediglich den internen Namen von ".txt" kennen, und kann dann die Verknüpfung durchführen:

Delphi-Quelltext
1:
2:
3:
  s := ftr.GetInternalName('.txt');
if(s <> ''then
  ftr.RegisterType('.foo',s);


Bei Entfernen darf nun natürlich auf keinen Fall "UnregisterType" benutzt werden, weil dadurch auch der interne Schlüssel der Textdateien gelöscht werden würde. Stattdessen gibt es "UnregisterExtension", die lediglich den Schlüssel ".foo" entfernt:

Delphi-Quelltext
1:
  ftr.UnregisterExtension('.foo');                    


Und noch ein Vorteil: Ich kann vorhandene Dateitypen ergänzen, ohne dass ich den internen Schlüssel kennen muss. Die Dateiendung reicht. Wenn ich einen eigenen Handler für Textdateien anlegen will, damit mein Programm als zusätzliche Option erscheint, genügt:

Delphi-Quelltext
1:
2:
  if(ftr.RegisterType('.txt','WhoTheF***Cares')) then
  ftr.AddHandler('MyOwnApp','c:\folder\foo.exe "%1"');

Das Besondere dabei ist, dass ich hier zwar den internen Namen "WhoTheF***Cares" benutzt habe, dass aber die Funktion "RegisterType" zuerst prüft ob der Typ bereits bekannt ist. In dem Fall wird dann der tatsächliche interne Schlüssel gesucht und benutzt. Nur wenn es den Typ nicht geben würde, dann würde natürlich meine Vorauswahl verwendet werden.

Auf die gleiche Weise wie o.g. kann ich natürlich auch diesen zusätzlichen Handler wieder entfernen, ohne dass das irgendwelche Auswirkungen auf die Textdateien an sich hätte.


Delete - Fr 02.07.04 22:30

Wer gern rumspielt, der kriegt hier gleich noch die C#-Version zum Registrieren von Dateitypen. Die Klasse steckt in der Datei "FileTypeRegistrationClass.cs", das SharpDevelop-Beispiel funktioniert im Prinzip wie das Delphi-Beispiel.

Aber bitte mit Vorsicht genießen.
Und evtl. Bugs o.ä. bitte melden.

:)


BenBE - Mo 21.08.06 18:59

Inwiefern unterstützt die Klasse den OpenWith-Handler zum Registrieren? Gab's neulich nen Post dazu hier im DF (such ich Dir ggf. auch raus).