![]() |
Kontextsensitive Hilfe aus Programm zu PDF
Hallo zusammen,
ich betreue eine Handvoll alte Programme in Delphi 2007. Bisher liegt auf jeden Formular ein Button für kontextsensitive Hilfe. Drückt der User darauf, öffnet sich die zum Formular passende Seite in der CHM-Datei. Realisiert wurde das damals mit der Komponente TContextHelp 1.0 von Easycash Software (gibts nicht mehr). Diese Komponente wiederum verwendet THelpRouter von EC Software ( ![]() Am Ende wird HtmlHelp aus der Windows-Unit aufgerufen und die CHM-Datei öffnet sich an der korrekten Position. Meine Frage: Gibt es die Möglichkeit, derartige Verlinkungen auch zu einen PDF-Dokument zu machen? Wenn ja, wie würde sowas aussehen? Man müsste auch Stichwort/Überschriften-spezifisch arbeiten können, weil die Doku sich zukünftig erweitern kann und man daher nicht "Öffne Seite 73" zum einen PDF-Reader mit ShellExecute sagen darf. Hintergrund: Unsere Dokumentationsabteilung verwendet zur Erstellung der Hilfe Microsoft Word und leider kein Tool wie Help+Manual. Das Erstellen einer PDF aus den Word-Dokument geht natürlich problemlos, nur das Konvertieren in eine CHM-Datei scheint einige Mühe zu machen und Zeit zu kosten. Ich bin für Ideen, Code-Schnipsel, Links zum Weiterlesen und/oder Erfahrungsberichte dankbar! |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Ich habe sowas vor Kurzem von Hand gemacht. Habe die PDF selbst eingelesen/geparst und die benötigte Seitennummer rausgelesen und dann die PDF auf dieser Seite mit dem Acrobatreader geöffnet (geht über die
![]() Wenn du die Seite schon weißt, dann kannst du die PDF ja wie oben genannt einfach aufrufen. |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Liste der Anhänge anzeigen (Anzahl: 1)
Oh, so etwas habe ich für die nächsten Tage auch auf der Agenda. Mein Plan war einfach die Bedienungsanleitung als PDF abzulegen und im passenden Kapitel aufzuschlagen.
Ich hänge dir mal eine Liste der Adobe Aufrufparameter an, keine Ahnung mehr wo ich das herhatte. Ansonsten hier einmal was ich irgendwann einmal angefangen hatte. Das geht allerdings fest auf den Adobe-Reader da wir nur fertige Systeme ausliefern und den vorinstalllieren. Mit einem beliebigen PDF-Viewer kann man das natürlich nicht verwenden.
Delphi-Quellcode:
unit PdfViewer experimental;
interface type TParams = record public type TPageMode = (none, bookmarks, thumbs); public var forceNewInstance: Boolean; filePath: String; startPage: Word; pageMode: TPageMode; /// <remarks> /// Scheint in Acrobat Reader DC keine Auswirkung zu haben sondern /// sich die Einstellung für jedes Dokument einzeln zu merken /// </remarks> showToolbar: Boolean; showStatusBar: Boolean; showNavPanes: Boolean; public procedure reset(); end; {TODO -oJM -cCleanup : Umbenennen in TAcroLauncher oder sowas} TPdfViewer = class(TObject) protected class function getCmdLineArguments(const forParams: TParams): PChar; virtual; public const executableName = 'AcroRd32'; public class procedure ShowAsync(const params: TParams); virtual; end; implementation uses System.SysUtils, System.Types, WinApi.ShellApi, WinApi.Windows, Spring.Utils ; type /// <summary> /// Schreibt Booleans als '0' oder '1' /// </summary> TStringBuilderHelper = class helper for System.SysUtils.TStringBuilder function Append(const Value: Boolean): TStringBuilder; overload; end; { TPdfViewer } class procedure TPdfViewer.ShowAsync(const params: TParams); var info: SHELLEXECUTEINFO; begin info := Default(SHELLEXECUTEINFO); info.cbSize := SizeOf(SHELLEXECUTEINFO); info.fMask := SEE_MASK_DEFAULT; info.lpVerb := 'open'; info.lpFile := executableName; info.nShow := SW_SHOWNORMAL; info.lpParameters := getCmdLineArguments(params); Win32Check( ShellExecuteEx( Addr(info)) ); end; class function TPdfViewer.getCmdLineArguments(const forParams: TParams): PChar; var stringBuilder: TStringBuilder; begin stringBuilder := TStringBuilder.Create(); try if forParams.forceNewInstance then stringBuilder.Append('/n '); stringBuilder.Append('/A '); stringBuilder .Append('"') .Append('page=') .Append(forParams.startPage) .Append('&toolbar=') .Append(forParams.showToolbar) .Append('&statusbar=') .Append(forParams.showStatusBar) .Append('&navpanes=') .Append(forParams.showNavPanes) .Append('&pageMode') .Append( TEnum.GetName(forParams.pageMode) ) .Append('"').Append(Space); stringBuilder.Append('"').Append(forParams.filePath).Append('"'); Result := PChar( stringBuilder.ToString() ); finally stringBuilder.Destroy(); end; end; { TParams } procedure TParams.reset(); begin filePath := EmptyStr; startPage := 1; showToolbar := False; showStatusBar := False; showNavPanes := False; forceNewInstance := True; pageMode := TPageMode.none; end; { TStringBuilderHelper } function TStringBuilderHelper.Append(const Value: Boolean): TStringBuilder; begin Result := Append( Value.ToString(TUseBoolStrs.False) ); end; end. |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Eventuell kann man statt das manuell zu parsen schauen, wie synctex (nach pdflatex + synctex googlen) das macht.
Dann muss man die Hilfedateien halt mit Latex erzeugen, dadurch werden die aber eh besser. |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Wenn ich mir das von Neutral General verlinkte PDF von Adobe so anschaue, müsste das mit Named Destinations machbar sein, ggf. in Verbindung mit Bookmarks/Lesezeichen. Ich würde auf jeden Fall davon Abstand nehmen, programmspezifische Parameter zu benutzen, also z.B. solche, die nur im Adobe Reader funktionieren, denn wer sagt denn, dass dieser in jedem Fall installiert und/oder das Standardprogramm für PDFs ist?
MfG Dalai |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Zitat:
Man nimmt einfach eine PDF Datei und die durchsuche ich nach bestimmten Merkmalen. Wenn ich ein solches Merkmal gefunden habe, mache ich ein "Ziel" draus und schon kann man dies von außen anspringen. Geht ganz gut für unsere Steuerung, wenn man beispielsweise ein Hilfe integrieren will. Gemacht alles mit ![]() |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Zitat:
Kann ich mir das vereinfacht so vorstellen, dass der Ersteller der PDF irgendwie zu den jeweiligen Themen eine "Named Destination" erstellt und ich dann per ShellExecute die PDF mit den dafür registrierten Programm öffne und durch den "Named Destinations"-Parameter springt das Ganze zur passenden Stelle?
Delphi-Quellcode:
ShellExecute(Application.Handle,
'open', PChar('C:\TestPath\myfile.pdf#nameddest=custom1'), nil, nil, SW_NORMAL) |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Zitat:
MfG Dalai |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Zitat:
Ich halte mal Rücksprache und berichte dann. |
AW: Kontextsensitive Hilfe aus Programm zu PDF
Heute endlich eine PDF mit Named Destinations von der Doku-Abeteilung bekommen.
Ich dachte ich bekomme es gar nicht hin, aber jetzt ist der Knoten geplatzt. Also grundsätzlich gehts! Der folgende Quellcode ist nicht schön, funktioniert aber soweit und sucht auch selbstständig den aktuell eingestellten PDF-Reader raus. Getestet mit den neusten FoxIt- und Acrobat Reader.
Delphi-Quellcode:
uses
System.Win.Registry, Winapi.ShellApi; const NAMED_DESTINATION_PREFIX = '/A "nameddest='; REG_SHELL_OPEN_COMMAND = '\Shell\Open\Command'; COMMAND_OPEN = 'open'; function GetAssociation(const DocFileName: string): string; var FileExtension : string; FileClass: string; Reg: TRegistry; begin Result := ''; Reg := TRegistry.Create(KEY_EXECUTE); try Reg.RootKey := HKEY_CLASSES_ROOT; FileClass := ''; FileExtension := ExtractFileExt(DocFileName); if Reg.OpenKeyReadOnly(FileExtension) then begin FileClass := Reg.ReadString(''); Reg.CloseKey; end; if FileClass <> '' then begin if Reg.OpenKeyReadOnly(FileClass + REG_SHELL_OPEN_COMMAND) then begin Result := Reg.ReadString(''); Reg.CloseKey; end; end; finally Reg.Free; end; end; procedure DoOpenPDF(const PDFReader, FileName, NamedDestination: string); var ExecuteResult: HINST; Parameters: string; begin Parameters := NAMED_DESTINATION_PREFIX + NamedDestination + '" "' + FileName + '"'; ExecuteResult := ShellExecute( Application.Handle, COMMAND_OPEN, PChar(PDFReader), PChar(Parameters), nil, SW_NORMAL ); if ExecuteResult < 32 then RaiseLastOSError; end; procedure OpenPDF(const FileName: string; const NamedDestination: string = ''); var PDFReader: string; begin PDFReader := GetAssociation('.pdf'); // 'FoxitReader.exe'; //'AcroRd32.exe'; PDFReader := ExtractFileName(PDFReader); PDFReader := PDFReader.Replace('" "%1"', '', [rfReplaceAll, rfIgnoreCase]); DoOpenPDF(PDFReader, FileName, NamedDestination); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:40 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz