Autor Beitrag
wasi
Hält's aus hier
Beiträge: 12

Win 95
D4 Standard
BeitragVerfasst: Do 18.12.03 20:08 
Hallo,

welche Schlüssel muss ich anlegen, wenn ich für meine Anwendung einen Dateityp registrieren will und ihm auch ein Icon verpassen möchte?
Hab mir zwar ma die Schlüssel in HKEY_CLASSES_ROOT angesehen, aber da gibt es soviele unterschiedliche Versionen, da wird man nicht wirklich schlau draus....
patrick
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 1481

WIN2k, WIN XP
D6 Personal, D2005 PE
BeitragVerfasst: Do 18.12.03 22:07 
es gibt dazu bereits ein faq im DF:
www.delphi-forum.de/viewtopic.php?t=78

das dürfte dir weiterhelfen

_________________
Patrick
im zweifelsfall immer das richtige tun!!!
wasi Threadstarter
Hält's aus hier
Beiträge: 12

Win 95
D4 Standard
BeitragVerfasst: Sa 20.12.03 16:11 
Danke, der Link hat meine Vermutungen bestätigt, aber auch neue Fragen aufgeworfen:

1. Was geben die Kommandozeilen-Parameter an (ich vermute: (0) Pfad der Anwendung, (1) Pfad der aufrufenden Datei, aber (2) ???)?
2. Was bedeuten die Optionen "/o" und "/p" an Ende der WriteString-Befehle, was bedeutet "%1"? Gibt es da spezielle Abwandlungen bzw. eine Übersicht über alle Befehle?
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 20.12.03 20:17 
Meine persönliche Meinung zu diesem FAQ-Beitrag: Fehlerhaft und auch nicht gerade universell nutzbar. Es mag funktionieren, aber es ist eben auf das jeweilige Programm zugeschnitten. Du musst zuviel ändern.

Und genau dadurch ergeben sich Fragen wie:
wasi hat folgendes geschrieben:
Was bedeuten die Optionen "/o" und "/p" an Ende der WriteString-Befehle, was bedeutet "%1"? Gibt es da spezielle Abwandlungen bzw. eine Übersicht über alle Befehle?

@wasi: Geht jetzt nicht gegen dich! Diese Befehle gehören wohl zu dem Programm, aus dem Arakis den Code genommen hat. Es liegt bei dir, zusätzliche Parameter usw. anzugeben, denn du reagierst über paramstr (s. Delphi-Hilfe) darauf.

Man müsste evtl. mal eine neue, universell nutzbare Funktion schreiben. :)
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 20.12.03 20:30 
MathiasSimmack hat folgendes geschrieben:
Man müsste evtl. mal eine neue, universell nutzbare Funktion schreiben. :)

Ich hatte gerade ein Deja vù. Mir ist, als hätten wir so was schon mal gemacht. Eine Funktion, der man alle notwendigen Angaben als Parameter übergeben konnte. Aber wo um alles in der Welt steckt der Beitrag dazu? :?
wasi Threadstarter
Hält's aus hier
Beiträge: 12

Win 95
D4 Standard
BeitragVerfasst: So 21.12.03 02:44 
Ich bin auch schon zu dem Schluss gekommen, dass mich wenn überhaupt nur die erste Hälfte von dem FAQ-Artikel interessiert, aber die Bedeutung der Parameter wüsste ich unabhängig von der Verwendbarkeit für mich trotzdem gerne. Ist halt Windows-Allgemeingut, oder nicht? Und das mit dem "%1" steht irgendwie immer am Ende, wenn man sich mal die registry ansieht. Aber mir reicht es nicht zu wissen, dass es da stehen muss, sondern ich wüsste gerne warum es da zu stehen hat....
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 21.12.03 05:06 
MathiasSimmack hat folgendes geschrieben:
Aber wo um alles in der Welt steckt der Beitrag dazu? :?

also in der DP habe ich auf die Schnelle das gefunden:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
uses ComObj; 
const 
  Extension = '.ella'
  Schluessel = 'Ellabetsch'// Luckie? 
  Beschreibung = 'Irgendwas'
var 
  Anwendung : string
procedure TForm1.RegisterButtonClick(Sender: TObject); 
begin 
  Anwendung := '"' + paramstr(0) + '" "%1"'
  try 
    CreateRegKey(Extension,'',Schluessel); 
    CreateRegKey(Schluessel,'',Beschreibung); 
    CreateRegKey(Schluessel + '\shell\open\command','',Anwendung); 
  except 
    on EOleRegistrationError do 
    ShowMessage('Mist! Hat nicht geklappt'); 
  end
end

procedure TForm1.UnregisterButtonClick(Sender: TObject); 
begin 
  try 
    DeleteRegKey(Extension); 
    DeleteRegKey(Schluessel); 
  except 
  end
end;
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 21.12.03 10:02 
Nee, @Luckie, das war´s irgendwie nicht. Ich muss mal gucken, ob ich den Code noch irgendwo lokal auf der Platte habe. Ansonsten schreibe ich die Funktionen eben noch mal, wenn sich der Beitrag nicht anfindet.

Das war (zum Registrieren) eine (Form-unabhängige) Prozedur, der du gleich alles als Parameter übergeben konntest: Pfad+Name der Anwendung, Beschreibung, gewünschtes Symbol, usw.

wasi hat folgendes geschrieben:
Und das mit dem "%1" steht irgendwie immer am Ende, wenn man sich mal die registry ansieht.

Die %1 symbolisiert den Dateinamen, der deinem Programm übergeben wird. Wenn du bspw. eine Textdatei (sagen wir "liesmich.txt") anklickst, dann schaut Windows nach, wie es mit Textdateien umgehen muss und findet bspw. diesen Befehl
ausblenden Quelltext
1:
notepad.exe "%1"					

Der letzte Parameter wird dann durch den Namen der angeklickten Datei ersetzt:
ausblenden Quelltext
1:
notepad.exe "c:\blablabla\liesmich.txt"					

und der Texteditor Notepad muss dann diesen Parameter (noch mal, s. paramstr in der Delphi-Hilfe) auslesen und entsprechend reagieren. In dem Fall also: die Datei laden und anzeigen.

Mehr steckt eigentlich nicht dahinter. Wenn man das Prinzip kennt, nach dem Dateitypen registriert werden (müssen), ist alles ganz einfach. ;)
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 21.12.03 11:42 
Also, den alten Beitrag habe ich nicht mehr gefunden. Darum hier mein neuer Vorschlag zum Diskutieren. Ich habe ingesamt 5 Funktionen geschrieben:
  1. RegisterFileType legt nur den neuen Dateityp an, irgendwelche Verknüpfungen mit Programmen usw. werden nicht erstellt.
  2. UnregisterFileType entfernt den neuen Dateityp ink. aller evtl. vorhandenen Unterschlüssel
  3. AddFileHandler legt eine neue Aktion an (open, print ... was immer man will) und verknüpft diese mit einem Programm
  4. DelFileHandler entfernt die angegebene Aktion wieder
  5. SetDefaultHandler legt fest, welche Aktion bei einem Doppelklick im Explorer ausgeführt werden soll

Das hört sich evtl. umständlich an, hat jedoch den Vorteil, dass man bereits vorhandene Dateitypen mit eigenen Aktionen erweitern kann, bzw. dass sich diese eigenen Aktionen natürlich auch wieder entfernen lassen, ohne gleich den kompletten Dateityp zu entfernen.

Hier der Code:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
uses
  Registry, ShlObj;

function RegisterFileType(const szExtension,
  szInternalName,
  szDescription,
  szFileIcon : string): boolean;
var
  reg : TRegistry;
begin
  // benötigt Admin-Rechte zum Schreiben in HKEY_CLASSES_ROOT
  Result := (IsAdmin) and
  // die Dateiendung sollte mehr als 1 Zeichen haben, denn ...
    (length(szExtension) > 1and
  // ... das erste Zeichen muss ein Punkt sein
    (szExtension[1] = '.'and
  // und die anderen Parameter dürfen nicht leer sein
    (szInternalName <> ''and
    (szDescription <> ''and
    (szFileIcon <> '');

  if(Result) then
  begin
    Result := false;
    reg    := TRegistry.Create;
    if(reg <> nilthen
    try
      reg.RootKey := HKEY_CLASSES_ROOT;

      // lege Schlüssel für Dateiendung mit Verweis auf
      // internen Namen an
      if(reg.OpenKey(szExtension,true)) then
      try
        reg.WriteString('',szInternalName);
        Result := (reg.ReadString('') = szInternalName);
      finally
        reg.CloseKey;
      end;

      // lege Schlüssel mit internem Namen an
      if(Result) and
        (reg.OpenKey(szInternalName,true)) then
      try
        // Beschreibung für Dateityp eintragen
        reg.WriteString('',szDescription);
        Result := (Result) and
          (reg.ReadString('') = szDescription);

        if(reg.OpenKey('DefaultIcon',true)) then
        try
          reg.WriteString('',szFileIcon);
          Result := (Result) and
            (reg.ReadString('') = szFileIcon);
        finally
          reg.CloseKey;
        end;
      finally
        reg.CloseKey;
      end;
    finally
      reg.Free;
    end;

    // das System über die Änderung "informieren"
    SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST,nil,nil);
  end;
end;

function UnregisterFileType(const szExtension: string): boolean;
var
  reg : TRegistry;
  s   : string;
begin
  Result := (IsAdmin) and
    (length(szExtension) > 1and
    (szExtension[1] = '.');

  if(Result) then
  begin
    reg    := TRegistry.Create;
    if(reg <> nilthen
    try
      reg.RootKey := HKEY_CLASSES_ROOT;

      // internen Schlüsselnamen für diesen Dateityp
      // ermitteln
      if(reg.OpenKey(szExtension,false)) then
      try
        s := reg.ReadString('');
      finally
        reg.CloseKey;
      end;

      // den Hauptschlüssel (= Dateiendung) löschen
      Result := (reg.DeleteKey(szExtension)) and
      // den ermittelten internen Schlüssel ebenfalls löschen
        (s <> ''and
        (reg.KeyExists(s)) and
        (reg.DeleteKey(s));
    finally
      reg.Free;
    end;

    SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST,nil,nil);
  end;
end;


const
  szKeyName = '%s\shell\%s';

function AddFileHandler(const szInternalName,
  szHandlerName,
  szHandlerDescription,
  szCommandLine: string): boolean;
var
  reg : TRegistry;
begin
  Result := (IsAdmin) and
    (szInternalName <> ''and
    (szHandlerName <> ''and
    (szCommandLine <> '');
  // "szHandlerDescription" ist optional und wird
  // nicht geprüft

  if(Result) then
  begin
    reg    := TRegistry.Create;
    if(reg <> nilthen
    try
      reg.RootKey := HKEY_CLASSES_ROOT;

      // der Schlüssel "szInternalName" muss existieren
      if(reg.KeyExists(szInternalName)) then
      begin
        // dann wird ein entsprechender Unterschlüssel mit
        // der gewünschten Aktion erzeugt
        if(reg.OpenKey(Format(szKeyName + '\command',
          [szInternalName,szHandlerName]),true)) then
         try
          // die angegebene "Kommandozeile" wird als
          // Standard eingetragen
          reg.WriteString('',szCommandLine);
          Result := (reg.ReadString('') = szCommandLine);
        finally
          reg.CloseKey;
        end;

        // gibt es eine Beschreibung?
        if(szHandlerDescription <> ''then
          if(reg.OpenKey(Format(szKeyName,
            [szInternalName,szHandlerName]),true)) then
          try
            reg.WriteString('',szHandlerDescription);
          finally
            reg.CloseKey;
          end;
      end;
    finally
      reg.Free;
    end;
  end;
end;

function DelFileHandler(const szInternalName,
  szHandlerName : string): boolean;
var
  reg : TRegistry;
begin
  Result := (IsAdmin) and
    (szInternalName <> ''and
    (szHandlerName <> '');

  if(Result) then
  begin
    reg := TRegistry.Create;
    if(reg <> nilthen
    try
      reg.RootKey := HKEY_CLASSES_ROOT;
      Result      :=
        (reg.KeyExists(Format(szKeyName,[szInternalName,szHandlerName]))) and
        (reg.DeleteKey(Format(szKeyName,[szInternalName,szHandlerName])));
    finally
      reg.Free;
    end;
  end;
end;

function SetDefaultHandler(const szInternalName,
  szDefaultHandler: string): boolean;
var
  reg : TRegistry;
begin
  Result := (IsAdmin) and
    (szInternalName <> ''and
    (szDefaultHandler <> '');

  if(Result) then
  begin
    reg := TRegistry.Create;
    if(reg <> nilthen
    try
      reg.RootKey := HKEY_CLASSES_ROOT;

      if(reg.KeyExists(szInternalName)) and
        (reg.OpenKey(szInternalName + '\shell',false)) then
      try
        reg.WriteString('',szDefaultHandler);
        Result := (reg.ReadString('') = szDefaultHandler);
      finally
        reg.CloseKey;
      end;
    finally
      reg.Free;
    end;
  end;
end;

Da der Schreibzugriff auf HKEY_CLASSES_ROOT nur funktioniert, wenn man min. Admin-Rechte hat (unter NT, 2000 und XP), habe ich die Funktion Suche in der Delphi-PRAXiS ISADMIN von NicoDE mit eingebaut. Einfach den Suchlink für die DP anklicken, dann solltet ihr fündig werden. So viele Beiträge sind´s nicht, und in einem davon hat Luckie die komplette Funktion gepostet.

Das Beispiel für einen eigenen Dateityp:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
procedure TForm1.Button1Click(Sender: TObject);
begin
  if(RegisterFileType(
    // 1. Parameter = Dateiendung inkl. führendem Punkt
    '.bla',
    // Verweis auf den internen Schlüsselnamen
    'BlaFile',
    // Beschreibung, die im Explorer angezeigt wird
    'BLA-Datei von Simmi',
    // Symbol für diesen Dateityp ist das Symbol der Exe
    paramstr(0))) then

// Wer mehrere Symbole in der Exe hat, muss den Index
// (null-basierend) zusätzlich angeben. Wenn etwa der Dateityp
// das dritte Symbol aus der Exe benutzen soll, dann

//  paramstr(0) + ',2'


  begin
    if(AddFileHandler(
      // noch einmal der Verweis auf den internen Schlüsselnamen
      'BlaFile',
      // der gewünschte "Handler" (= Aktion/Verb), hier "open"
      'open',
      // Beschreibung für das Kontextmenü des Explorers
      // (optional, kann auch ein Leerstring sein!)
      'BLA-Datei öffnen',
      // und die gewünschte Kommandozeile
      // (hier also der Texteditor)
      'notepad.exe "%1"')) then ShowMessage('ok');

    // das gleiche als Beispiel für "print", ...
    AddFileHandler('BlaFile','print','','notepad.exe /p "%1"');

    // "print" als Standardaktion festlegen, d.h. bei einem
    // Doppelklick wird der Druckbefehl ausgeführt
    SetDefaultHandler('BlaFile','print');
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  UnregisterFileType('.bla');
end;


Und als Beispiel #2, die Erweiterung von Textdateien für das eigene Programm:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
AddFileHandler('txtfile',
  'OpenWithMyself',
  'Mit Programm XY öffnen',
  '"' + paramstr(0) + '" "%1"');


// "txtfile" ist der interne Name von Textdateien. Darauf sollte
// man sich aber nicht verlassen. Ich empfehle darum, den
// tatsächlichen Namen immer aus der Registry zu lesen, damit man
// auch wirklich auf den richtigen Schlüssel zugreift. Also,
// einfach nur den Standardwert der gewünschten Dateiendung ermitteln,
// und man hat den Schlüssel

Wenn man nun sein Programm löscht oder deinstalliert, dann will man natürlich auch diese neue Aktion entfernen, ohne dabei gleich den kompletten Typ der Textdateien rauszuschmeißen. Und da kommt dann "DelFileHandler" ins Spiel:
ausblenden Delphi-Quelltext
1:
DelFileHandler('txtfile','OpenWithMyself');					


Tja, jetzt seid ihr dran. :)
Irgendwelche Verbesserungsvorschläge?
Optimierungen?
Ergänzungen?
Sonst was?

Gruß.
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: Fr 18.03.05 21:52 
und wie kann ich prüfen ob die gesuchte endung auch mit meinem programm verküpft ist ?
also so in etwa:
if midi = "mein progamm" then ChecklistBox1.items[0]:=True

deine funktionen sehen nicht schlecht aus *G*

_________________
MFG
Michael Springwald, "kann kein englisch...."
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: Fr 18.03.05 21:58 
habe nach ISADMIN gesucht aber nichts gefunden, werde einfach diese anweisung aus dem qullcode löschen...(bin ja admin bei mir am rechner :D )

_________________
MFG
Michael Springwald, "kann kein englisch...."
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 18.03.05 22:35 
Natürlich, und mein Windows liegt auf der K-Partition. Also werde ich mir nicht mehr die Mühe machen, das Windows- oder Systemverzeichnis mit den API-Funktionen zu ermitteln. Ich schreib einfach K:\ rein. Funktioniert ja bei mir auf meinem Rechner. :roll: Man kann sich das Leben auch schwer machen und sich beim Suchen nach IsAdmin auch besonders dumm anstellen.
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: Sa 19.03.05 21:34 
in der AddFileHandler ist ein fehler drin(2)
szKeyName wird nicht gefunden :cry: ich habe es einfach in szHandlerName geändert aber: das symbol erscheint richtig aber wenn ich auf diese datei draufklicke wird was falsches gemacht:
(so rufe ich es auf)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
// der inhalt der checklisbox:
WAV
MP2
MP3
OGG
WMA
ASF
MOD
S3M
XM
IT
MID
RMI
SGT

procedure TForm3.BitBtn1Click(Sender: TObject);
var
  i:Integer;
begin
  for i:=0 to CheckListBox1.Items.Count-1 do begin
    if CheckListBox1.Checked[i] = True then begin
      RegisterFileType('.' + CheckListBox1.Items[i],CheckListBox1.Items[i] + 'file',CheckListBox1.Items[i] + ' Dateien',GetExeDir + 'icons\' + CheckListBox1.Items[i] + '.ico');
      AddFileHandler(CheckListBox1.Items[i] + 'file','Play',paramstr(0) + '"\L"','Spielte diese Datei ab');
      SetDefaultHandler(CheckListBox1.Items[i] + 'file','Play');
    end;
  end;
  close;
end;

_________________
MFG
Michael Springwald, "kann kein englisch...."
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 20.03.05 10:56 
Da ist kein Fehler drin, du hast, fürchte ich, das Prinzip der Codezeilen überhaupt nicht verstanden. Aber das ist ohnehin ein relativ alter Beitrag, und darum kurz und bündig: klick.
Golden-Melody
Hält's aus hier
Beiträge: 2

Win XP

BeitragVerfasst: So 10.04.05 01:44 
Nach dem Programmnamen folgen die Parameter, die an das Programm in der
Form %1 [%2] [%3] ... usw. übergeben werden. Da die meisten Programme, die
in der Registry eingetragen sind, nur einen Parameter, nämlich den Dateiname
der zu bearbeitenden Datei erwarten, ist dies im Allgemeinen %1. Diese Schreib-
weise stammt aus der Batchprogrammierung unter DOS. (Gott waren das Zeiten):lol:

In der Eingabeaufforderung (DOS Fenster) von Windows einfach mal den folgenden
Befehl eingeben. Da steht dann eine Erklärung a'la MicroSoft.

>help ftype
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: So 10.04.05 09:39 
Danke. %l steht da garnicht aber %* werde ich gleich mal ausprobieren *G*

_________________
MFG
Michael Springwald, "kann kein englisch...."