Microsoft als Betriebssystem-Monopolist hat sich etwas ausgedacht, damit der ansonsten zumindest bei Webdesignern und etwas bewanderteren Anwendern eher unbeliebte Internet Explorer einen Lebenszweck behält. Und zwar das „res:“ Protokoll. Ich habe das mal mit DelphiXE ausprobiert.
Ich bin ein Dokumentations- und Erklärungsfan. Deshalb gibt es — abgesehen von einigen wenigen, ausschließlich für den Eigenbedarf geschaffenen Progrämmchen — bei meinen Programmen immer in irgend einer Form eine Hilfe. Vorzugsweise direkt im Programm, denn dann geht nichts verloren.
Allerdings bedeutet das typischerweise, dass ich die Hilfe mit einer integrierten Darstellungsfunktion präsentieren muss, was den Entwicklungsaufwand, speziell bei kleinen Helfern teilweise erheblich steigert. Für *Einfachst-Dokumentation* ist das „res:“ Protokoll aber gar nicht so schlecht, vorausgesetzt, der Internet Explorer wurde nicht deinstalliert. Dann läuft es nämlich ins Leere und die Hilfe versagt. Da das jedoch zumindest bei den Hilfe-Bedürftigen eher die Ausnahme ist, lassen wir das mal außen vor.
Im Grunde ist es brutalst einfach (wenn man sich durch die z.T. sinnlos langen, umständlichen und teilweise falschen Ratschläge dazu gekämpft hat):
- Ich binde eine HTML-Datei als Ressource mit dem Typ
RT_HTML
in das Programm ein. - Ich rufe sie mit dem „res:“ Protokoll aus der Datei auf.
Nehmen wir an, ich will die Datei Anleitung.html
als Ressource-Datei einlagern und aufrufen. In DelphiXE (und mutmaßlich analog mit den Vorgängern und Nachfolgern) lade ich die Datei als Ressource, gebe ihr den (in der Vorschlagsliste der Typen nicht enthaltene) Typ RT<em>HTML
und den Bezeichner ANLEITUNG
. Der Typ ist entscheidend. Nur dann klappt der nächste Schritt.
Der Aufruf ist „stumpf“:
<?php var Die_Anleitung : String;
...
Die_Anleitung := 'res://' + ChangeFileExt(ParamStr(0),'.exe') + '/RT_HTML/ANLEITUNG';
ShellExecute(Handle, nil, PChar(Die_Anleitung), nil, nil, SW_SHOWNORMAL);
Das ChangeFileExt ist womöglich nicht die cleverste Lösung, denn ich tausche den Extender gar nicht. Dafür bekomme ich aber stressfrei den kompletten Pfad inklusive Extender, was der Internet Explorer offenbar braucht. Zumindest unter Windows 8.1 mit dem IE 11.
Ab wann und auf welchen Betriebssystemen das „res“ Protokoll von welchem IE unterstützt wird, weiß ich nicht. Nach vorn blickend ist diese Methode jedoch durchaus interessant.
Der kleine Haken
Bei meinen (zeitlich überschaubaren) Versuchen hat sich der IE störrisch gezeigt, was die Interpretation von eingebetteten Style-Sheets betrifft. Grundsätzlich kann man Stylesheets und Bilder ebenfalls als Ressource einbetten, die dann (wahrscheinlich) verwendet werden. Allerdings haben mich an der Lösung zwei Dinge genervt, weshalb ich es dann doch anders realisiert habe:
- Eine HTML-Datei soll in dem Browser aufgehen, den ich als Benutzer gewählt habe und nicht in einer in vielen Fällen bewusst dafür nicht als Standard eingestellten Anwendung.
- Die HTML-Datei soll so aussehen, wie sie erstellt wurde.
Meine Lösung
Ich habe mich statt dessen entschieden, die Hilfe zu extrahieren und mit dem Standardbrowser aufzurufen. Wenn das Programm geschlossen wird, wird die Hilfe-Datei gelöscht, so entstehen keine Datei-Leichen. Da meine Programme nicht installiert werden müssen, sondern typischerweise irgendwo im Benutzerverzeichnis liegen, gibt es bei diesem Verfahren keine Rechteprobleme, es sei denn, ein Anwender darf in seinem eigenen Verzeichnis keine Dateien speichern. Das wäre aber eher ungewöhnlich.
<?php procedure TFUplader.BTanleitungClick(Sender: TObject);
var RS: TResourceStream;
begin
if Die_Anleitung = '' then
// Anleitung war noch nicht offen, existiert also noch nicht
Begin
Die_Anleitung := ExtractFilePath(ParamStr(0)) + 'Anleitung.html';
RS := TResourceStream.Create(HInstance, 'ANLEITUNG', RT_RCDATA);
try
RS.SaveToFile(Die_Anleitung);
finally
RS.Free;
end;
End;
ShellExecute(Handle, nil, PChar(Die_Anleitung), nil, nil, SW_SHOWNORMAL);
end;
...
procedure TForm.FormCreate(Sender: TObject);
begin
// Globale Variable vorbesetzen
Die_Anleitung := '';
End;
...
procedure TForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// Wenn die Anleitung geöffnet war, wieder wegräumen
if Die_Anleitung <> '' then
DeleteFile(Die_Anleitung);
end;