Microsoft Compressed HTML Help File Viewer for Windows 10+
Version: v3 – moderne + Legacy-/Delphi-kompatible Schnittstelle
Technik: Python 3, PyQt5, QtWebEngine, Windows CHM
Anwendung: eigenständiger CHM-Viewer und externer Hilfe-Viewer für andere Anwendungen
- Ziel und Überblick
- Funktionsumfang
- Systemvoraussetzungen
- Datei- und Projektstruktur
- Installation
- Programmstart
- Benutzeroberfläche
- Dark Mode
- Persistente Fenster- und Splitter-Geometrie
- CHM-Dateien öffnen und entpacken
- Themen, Schlüsselwörter und Favoriten
- SVG-Unterstützung
- Moderne Kommandozeilenschnittstelle
- Legacy-/Delphi-Kompatibilität
- HTML-Help-Bridge
- Themen-String und Context-ID
- Priorität bei Hilfeaufrufen
- Metainformationen mit JSON
- Integration aus Python
- Integration aus Delphi
- Integration aus C/C++
- F1-Kontexthilfe
- CHM-Metadaten
- MAP- und ALIAS-Dateien
- Interne Architektur
- Klassen- und Funktionsreferenz
- Navigation und URL-Behandlung
- Sicherheitsmaßnahmen
- Favoriten-Speicherung
- Fehlerbehandlung und Diagnose
- Bekannte Grenzen
- Empfohlene Metadaten-Konvention
- Testplan
- Verteilung als EXE
- Erweiterungspunkte
- Kurzreferenz
Der CHM Viewer ist eine eigenständige Qt5-Anwendung zur Anzeige klassischer Microsoft-CHM-Hilfedateien. Die eigentliche Darstellung der HTML-Inhalte erfolgt über QtWebEngine/Chromium anstelle des alten Microsoft-CHM-Viewers.
Dadurch können moderne HTML-Inhalte und insbesondere lokale SVG-Grafiken innerhalb der entpackten Hilfe angezeigt werden.
Der Viewer verfolgt zwei Ziele:
-
Moderne eigene Hilfe-Schnittstelle
--topic--context-id--language--keyword--local
-
Kompatibilität mit älteren Hilfe-Konzepten
help.chm::/topic.html-mapid/context-keyword- HTML-Help-Kommandos wie
HH_HELP_CONTEXT
Beide Varianten werden intern auf dieselbe Navigationslogik abgebildet.
Der aktuelle Viewer bietet:
- Öffnen einer
.chm-Datei - Öffnen eines bereits entpackten Hilfe-Verzeichnisses
- automatische CHM-Extraktion
- Themenbaum aus
.hhc - Schlüsselwortindex aus
.hhk - Auswertung von
.hhp - Auswertung von
[MAP]und[ALIAS] - zusätzliche Suche nach
#define-Context-IDs in Header-Dateien - direkte Navigation zu einer lokalen HTML-Seite
- Navigation über Context-ID
- Navigation über Topic-/Wortsuche
- Navigation über Keyword
- Favoriten
- Zurück / Vor / Startseite
- Seiten-Quelltext
- globaler Dark Mode
- persistente Fenstergeometrie
- persistenter Splitter-Zustand
- persistenter Theme-Zustand
- lokale SVG-Unterstützung
- Legacy-/Delphi-kompatible Kommandozeilenargumente
- Source-Level-Delphi-Adapter
Der Viewer ist für Windows ausgelegt.
Die CHM-Extraktion verwendet bevorzugt:
hh.exe -decompile
Als Fallback kann 7-Zip verwendet werden.
Empfohlen:
Python 3.10 oder neuer
Die aktuelle Entwicklung wurde mit Python 3.x erstellt.
Erforderlich:
PyQt5
PyQtWebEngine
Installation:
py -m pip install PyQt5 PyQtWebEngineoder:
py -m pip install -r requirements.txtDas Paket besitzt folgende Struktur:
chmviewer_package_v3_legacy_compat/
│
├── chmviewer.py
├── requirements.txt
├── README.txt
├── helpmeta.example.json
│
└── delphi/
└── ChmViewerCompat.pas
Hauptprogramm mit:
- Qt5-GUI
- CHM-Extraktion
- Themen-/Keywordparser
- Context-ID-Auswertung
- Navigation
- Theme
- CLI-Kompatibilität
Python-Abhängigkeiten.
Beispiel für Metainformationen einer aufrufenden Anwendung.
Delphi-Adapter für Source-Level-Kompatibilität.
Optional:
py -m venv .venv
.venv\Scripts\activateDanach:
py -m pip install -r requirements.txtpy chmviewer.pyEs erscheint das leere Hauptfenster des Viewers.
py chmviewer.pypy chmviewer.py help.chmpy chmviewer.py help\py chmviewer.py help.chm --darkpy chmviewer.py help.chm --lightOhne --dark oder --light wird der zuletzt gespeicherte Modus verwendet.
Die Anwendung basiert auf QMainWindow.
Die grobe Struktur lautet:
QMainWindow
│
├── Menüleiste
├── Navigations-Toolbar
├── CentralWidget
│ └── QSplitter
│ ├── QTabWidget
│ │ ├── Themen
│ │ ├── Schlüsselwörter
│ │ └── Favoriten
│ │
│ └── QWebEngineView
│
└── StatusBar
Enthält:
- Hilfe öffnen …
- Hilfe-Verzeichnis öffnen …
- Programm beenden
Enthält:
- Kopieren
- Seiten-Quelltext
Enthält:
- Dark Mode
Enthält:
- Über …
Enthält:
- Hilfe öffnen
- Start
- Zurück
- Vor
Der Dark Mode gilt für die gesamte QApplication.
Damit werden nicht nur HTML-Seiten, sondern auch Qt-Widgets angepasst:
- Hauptfenster
- Menüs
- Toolbar
- Statusbar
- Eingabefelder
- QTreeWidget
- Tabs
- Dialoge
- Buttons
- Quelltextfenster
- Tooltips
- WebEngine-Hintergrund
Der Viewer benutzt:
QApplication.setPalette(...)
QApplication.setStyleSheet(...)Für den Web-Inhalt wird zusätzlich CSS injiziert.
Der Theme-Zustand wird über QSettings gespeichert:
ui/dark_mode
Beim Schließen speichert der Viewer:
ui/window_geometry
ui/window_state
ui/main_splitter_state
ui/dark_mode
Verwendete Qt-Funktionen:
saveGeometry()
restoreGeometry()
saveState()
restoreState()
QSplitter.saveState()
QSplitter.restoreState()Die Wiederherstellung erfolgt bereits im Konstruktor vor dem ersten sichtbaren show().
Dadurch erscheint das Fenster beim nächsten Start direkt:
- an der alten Position
- in der alten Größe
- mit dem vorherigen Splitter-Verhältnis
- im vorherigen Theme
Eine CHM-Datei wird nicht direkt durch Chromium gelesen.
Stattdessen:
CHM
│
▼
temporäres Verzeichnis
│
├── HTML
├── CSS
├── JavaScript
├── Bilder
├── SVG
├── HHC
├── HHK
└── HHP
│
▼
QWebEngineView
Unter Windows wird zuerst hh.exe gesucht.
Typische Kandidaten:
%WINDIR%\hh.exe
%WINDIR%\System32\hh.exe
%WINDIR%\SysWOW64\hh.exe
Aufruf:
hh.exe -decompile <Zielverzeichnis> <Datei.chm>
Der Viewer wartet bis zu etwa acht Sekunden auf extrahierte Inhalte.
Ist hh.exe nicht erfolgreich, wird nach folgenden Programmen gesucht:
7z
7za
7zr
Beispiel:
7z x -y -o<Ziel> help.chm
Das entpackte CHM wird in einem temporären Verzeichnis abgelegt.
Beim Schließen wird dieses Verzeichnis bereinigt.
Der Themenbaum wird normalerweise aus einer .hhc-Datei gelesen.
Die Sitemap wird mit HTMLParser ausgewertet.
Typische Struktur:
<OBJECT type="text/sitemap">
<param name="Name" value="PRINT">
<param name="Local" value="basic/print.html">
</OBJECT>Der Schlüsselwortindex wird aus .hhk gelesen.
Auch hier wird das klassische text/sitemap-Format verarbeitet.
Ist keine Themen-Sitemap vorhanden, durchsucht der Viewer das Hilfeverzeichnis nach:
*.html
*.htm
und erzeugt daraus einen einfachen Themenbaum.
Die Inhalte werden mit QWebEngineView dargestellt.
Daher können lokale SVG-Dateien eingebunden werden:
<img src="images/74ls00.svg" alt="74LS00">Voraussetzung ist, dass die SVG-Datei beim Entpacken Bestandteil der Hilfe ist.
Die Einstellung:
QWebEngineSettings.LocalContentCanAccessFileUrls = Trueerlaubt lokalen HTML-Dateien Zugriff auf weitere lokale Ressourcen.
Der Remote-Zugriff lokaler Inhalte wird dagegen deaktiviert:
QWebEngineSettings.LocalContentCanAccessRemoteUrls = Falsechmviewer.exe help.chm --topic PRINTchmviewer.exe help.chm --topic PRINT --language basicchmviewer.exe help.chm --context-id 2101Auch hexadezimale IDs sind möglich:
chmviewer.exe help.chm --context-id 0x835Empfohlen:
chmviewer.exe help.chm ^
--context-id 2101 ^
--topic PRINT ^
--language basicKann die ID nicht aufgelöst werden, steht weiterhin der lesbare Topic-String zur Verfügung.
chmviewer.exe help.chm --local basic/print.htmlchmviewer.exe help.chm --keyword PRINTBleibt kompatibel:
chmviewer.exe help.chm --word PRINT--word ist ein Alias für --topic.
Der Viewer akzeptiert mehrere ältere Schreibweisen.
chmviewer.exe "help.chm::/basic/print.html"Auch diese Formen werden erkannt:
mk:@MSITStore:help.chm::/basic/print.html
ms-its:help.chm::/basic/print.html
chmviewer.exe -mapid 2101 help.chmWeitere akzeptierte Aliase:
-mapid
-context
-contextid
/mapid
/context
/contextid
chmviewer.exe -keyword PRINT help.chmoder:
chmviewer.exe /keyword PRINT help.chmchmviewer.exe -topic basic/print.html help.chmoder:
chmviewer.exe /topic basic/print.html help.chmBei Legacy-Aufrufen bedeutet -topic beziehungsweise /topic einen direkten lokalen Pfad.
Beim modernen Aufruf bedeutet:
--topic
dagegen einen lesbaren Suchbegriff.
Dieser Unterschied ist bewusst gewählt.
Der Viewer besitzt zusätzlich eine explizite Bridge für bekannte HTML-Help-Kommandos.
Unterstützt sind derzeit:
HH_DISPLAY_TOPIC = 0x0000
HH_KEYWORD_LOOKUP = 0x000D
HH_HELP_CONTEXT = 0x000F
chmviewer.exe help.chm ^
--hh-command HH_HELP_CONTEXT ^
--hh-data 2101chmviewer.exe help.chm ^
--hh-command HH_DISPLAY_TOPIC ^
--hh-data basic/print.htmlchmviewer.exe help.chm ^
--hh-command HH_KEYWORD_LOOKUP ^
--hh-data PRINTDer Command darf auch numerisch übergeben werden.
Beispiel:
chmviewer.exe help.chm --hh-command 0x000F --hh-data 2101Für neue Anwendungen wird empfohlen, nicht nur eine einzige Information zu speichern.
Optimal ist:
Topic = PRINT
Context-ID = 2101
Language = basic
Local = basic/print.html
Warum?
Vorteil:
- stabil
- schnell
- klassisches Hilfe-Konzept
- gut für F1-Hilfe
Nachteil:
- für Menschen nicht lesbar
- Zuordnung muss in CHM-Metadaten vorhanden sein
Vorteil:
- lesbar
- funktioniert als Fallback
Nachteil:
- mehrere gleichnamige Themen möglich
Vorteil:
- eindeutig
Nachteil:
- Pfad kann sich bei Umstrukturierung ändern
Verfeinert einen Topic-Treffer.
set_pending_request() speichert eine Anfrage.
Beim Öffnen wird sie in folgender Reihenfolge verarbeitet:
1. Local
2. Context-ID / Topic
3. Keyword
4. Topic-Fallback
Genauer:
pending_local
│
├─ gefunden → öffnen
└─ nicht gefunden
│
▼
context_id oder topic
│
├─ Context-ID erfolgreich → öffnen
├─ Topic erfolgreich → öffnen
└─ kein Treffer
│
▼
keyword
Das Paket enthält:
helpmeta.example.json
Beispiel:
{
"viewer": "chmviewer.exe",
"help_file": "help/c64.chm",
"topics": {
"PRINT": {
"language": "basic",
"topic": "PRINT",
"context_id": 2101,
"local": "basic/print.html"
},
"GOTO": {
"language": "basic",
"topic": "GOTO",
"context_id": 2102,
"local": "basic/goto.html"
}
}
}Für jedes Hilfethema:
{
"language": "...",
"topic": "...",
"context_id": 0,
"local": "..."
}import subprocess
subprocess.Popen([
"chmviewer.exe",
"help/c64.chm",
"--topic",
"PRINT",
])subprocess.Popen([
"chmviewer.exe",
"help/c64.chm",
"--topic", "PRINT",
"--language", "basic",
"--context-id", "2101",
])HELP = {
"PRINT": {
"language": "basic",
"context_id": 2101,
"local": "basic/print.html",
},
}
def show_help(topic):
topic = topic.upper()
meta = HELP.get(topic)
if not meta:
return False
args = [
"chmviewer.exe",
"help/c64.chm",
"--topic", topic,
"--language", meta["language"],
"--context-id", str(meta["context_id"]),
]
subprocess.Popen(args)
return TrueDas mitgelieferte Unit:
delphi\ChmViewerCompat.pas
definiert:
HH_DISPLAY_TOPIC
HH_KEYWORD_LOOKUP
HH_HELP_CONTEXTund folgende Funktionen:
ChmViewerTopic(...)
ChmViewerContext(...)
ChmViewerKeyword(...)
ChmViewerHtmlHelp(...)ChmViewerTopic(
'chmviewer.exe',
'help\c64.chm',
'basic\print.html'
);ChmViewerContext(
'chmviewer.exe',
'help\c64.chm',
2101
);ChmViewerKeyword(
'chmviewer.exe',
'help\c64.chm',
'PRINT'
);ChmViewerHtmlHelp(
'chmviewer.exe',
'help\c64.chm',
HH_HELP_CONTEXT,
'',
2101
);Direktes Thema:
ChmViewerHtmlHelp(
'chmviewer.exe',
'help\c64.chm',
HH_DISPLAY_TOPIC,
'basic\print.html',
0
);Der Viewer kann mit CreateProcessW, ShellExecuteW oder ähnlichen Mechanismen gestartet werden.
Beispiel mit ShellExecuteW:
#include <windows.h>
void ShowHelpContext()
{
ShellExecuteW(
nullptr,
L"open",
L"chmviewer.exe",
L"\"help\\c64.chm\" --context-id 2101 --topic PRINT",
nullptr,
SW_SHOWNORMAL
);
}Direktes Thema:
ShellExecuteW(
nullptr,
L"open",
L"chmviewer.exe",
L"\"help\\c64.chm::/basic/print.html\"",
nullptr,
SW_SHOWNORMAL
);Ein typischer Ablauf in einer IDE oder einem Editor:
Benutzer drückt F1
│
▼
Wort unter Cursor bestimmen
│
▼
Metadaten nachschlagen
│
├── Topic
├── Context-ID
├── Sprache
└── Local
│
▼
chmviewer.exe starten
Beispiel:
def handle_f1(word):
word = word.strip().upper()
args = [
"chmviewer.exe",
"help/c64.chm",
"--topic", word,
"--language", "basic",
]
context_id = BASIC_HELP_IDS.get(word, 0)
if context_id:
args += ["--context-id", str(context_id)]
subprocess.Popen(args)Die wichtigsten klassischen Dateien:
*.hhp Projekt
*.hhc Contents / Themen
*.hhk Index / Schlüsselwörter
*.h Context-ID-Konstanten
Aus [OPTIONS] werden insbesondere berücksichtigt:
Contents file
Index file
Default topic
Erzeugt den Themenbaum.
Erzeugt den Schlüsselwortbaum.
Für numerische Context-IDs werden [MAP] und [ALIAS] aus der HHP ausgewertet.
Beispiel:
[MAP]
#define IDH_PRINT 2101
#define IDH_GOTO 2102
[ALIAS]
IDH_PRINT=basic/print.html
IDH_GOTO=basic/goto.htmlAlternativ können Definitionen auch in Header-Dateien stehen:
#define IDH_PRINT 2101
#define IDH_GOTO 2102Der Viewer durchsucht dazu *.h im entpackten Hilfeverzeichnis.
Das Ergebnis ist intern:
{
2101: "basic/print.html",
2102: "basic/goto.html"
}Kommandozeile
│
▼
normalize_legacy_argv()
│
▼
parse_args()
│
├── modern
├── legacy
└── HH bridge
│
▼
MainWindow.set_pending_request()
│
▼
CHM öffnen / entpacken
│
▼
HHC / HHK / HHP / MAP / ALIAS lesen
│
▼
apply_pending_help_request()
│
▼
QWebEngineView
MainWindow
├── Actions
├── MenuBar
├── ToolBar
├── QSplitter
│ ├── QTabWidget
│ │ ├── ChmSearchTab Topics
│ │ ├── ChmSearchTab Keywords
│ │ └── ChmSearchTab Favorites
│ └── QWebEngineView
└── QStatusBar
Dataclass:
title: str
local: str
children: List[ChmSitemapEntry]Repräsentiert einen HHC-/HHK-Eintrag.
Parser für klassische HTML-Help-Sitemaps.
Wichtige Methoden:
handle_starttag()
handle_endtag()Liest insbesondere:
<object type="text/sitemap">
<param name="Name" ...>
<param name="Local" ...>Verantwortlich für das Entpacken.
Methode:
ChmExtractor.extract(source, destination)Priorität:
hh.exe
↓
7-Zip
Wiederverwendbarer Tab mit:
QLineEdit- Suchbutton
QTreeWidget
Signal:
search_requested = pyqtSignal(str)Unterklasse von:
QWebEnginePageBehandelt:
- interne
mk:-/ms-its:-Links - externe HTTP-/HTTPS-/Mail-Links
Externe Links werden über:
QDesktopServices.openUrl()geöffnet.
Zeigt den HTML-Quelltext der aktuellen Seite.
Zentrale Hauptklasse.
open_chm()
open_help_directory()
read_metadata()
populate_tree()
load_local()
open_context_topic()
open_keyword_topic()
set_pending_request()
apply_pending_help_request()
add_current_favorite()
remove_current_favorite()
set_dark_mode()
save_ui_state()
restore_ui_state()Normalisiert interne CHM-Pfade.
Verarbeitet unter anderem:
mk:@MSITStore:
ms-its:
its:
::/
#
URL-Encoding
Backslashes
Verhindert außerdem Pfade mit ...
Löst einen internen Pfad im entpackten CHM auf.
Enthält einen case-insensitiven Fallback.
Das ist wichtig, weil CHM-Hilfen häufig inkonsistente Groß-/Kleinschreibung enthalten.
Erzeugt:
Dict[int, str]aus:
[MAP][ALIAS]*.h
Übersetzt bekannte alte Argumente.
Beispiel:
/context -> --context-id
/mapid -> --context-id
/keyword -> --keyword
/topic -> --local
Zerlegt:
help.chm::/basic/print.html
in:
CHM-Datei = help.chm
Local = basic/print.html
Akzeptiert:
HH_HELP_CONTEXT
HELP_CONTEXT
CONTEXT
0x000F
15
Interne Seiten werden mit:
QUrl.fromLocalFile(...)geladen.
Auch Anchor-Links werden unterstützt:
basic/print.html#syntax
Folgende Schemes können extern geöffnet werden:
http
https
mailto
Die Einstellung:
LocalContentCanAccessRemoteUrls = Falseverhindert, dass eine lokale Hilfeseite beliebig Remote-Ressourcen lädt.
Der Viewer enthält mehrere Schutzmaßnahmen.
clean_chm_local() verwirft:
../
Dadurch sollen Pfade nicht aus dem entpackten Root herausführen.
resolve_chm_path() kontrolliert über Path.resolve() und relative_to(), dass die Datei im Hilfe-Root liegt.
Lokale Seiten dürfen nicht automatisch Remote-URLs nachladen.
HTTP/HTTPS/Mailto werden aus der WebEngine heraus an das Betriebssystem übergeben.
Favoriten werden mit QSettings gespeichert.
Für jede Hilfe gibt es einen separaten Schlüssel.
Dieser wird aus dem Hilfe-Pfad erzeugt:
SHA-256(CHM-Pfad)
Schema:
chm/favorites/<hash>
Gespeicherter Inhalt:
[
{
"title": "PRINT",
"local": "basic/print.html"
}
]Dadurch vermischen sich Favoriten verschiedener Hilfedateien nicht.
Meldung:
PyQt5 / PyQtWebEngine fehlt.
Abhilfe:
py -m pip install PyQt5 PyQtWebEnginePrüfen:
hh.exe vorhanden?
7z vorhanden?
CHM beschädigt?
Schreibrecht im Temp-Verzeichnis?
Prüfen:
- Ist es in
.hhcoder.hhkvorhanden? - Entspricht der Dateiname dem Topic?
- Stimmt
--language? - Gibt es eine Context-ID?
- Ist der Local-Pfad korrekt?
Prüfen:
[MAP]
...
[ALIAS]
...sowie Header-Dateien.
Prüfen:
- SVG in CHM enthalten?
- relativer Pfad korrekt?
- Datei nach Extraktion vorhanden?
- HTML verweist auf lokalen Pfad?
Der aktuelle Delphi-Adapter ist Source-Level-Kompatibilität.
Das bedeutet:
Eine Delphi-Anwendung, die neu kompiliert wird, kann:
ChmViewerContext(...)verwenden.
Eine bereits kompilierte EXE, die intern direkt:
HtmlHelpA()
HtmlHelpW()
hhctrl.ocx
aufruft, wird nicht automatisch umgeleitet.
Dafür wäre ein zusätzlicher nativer Proxy nötig.
Aktuell werden explizit unterstützt:
HH_DISPLAY_TOPIC
HH_KEYWORD_LOOKUP
HH_HELP_CONTEXT
Andere Kommandos benötigen zusätzliche Adapterlogik.
hh.exe -decompile ist ein pragmatischer Weg.
Ungewöhnliche oder beschädigte CHMs können trotzdem Probleme verursachen.
Für das d64_dism-/dBase2Many-Projekt empfiehlt sich eine zentrale Hilfe-Metadatendatei.
Beispiel:
{
"basic": {
"PRINT": {
"context_id": 2101,
"local": "basic/print.html"
},
"GOTO": {
"context_id": 2102,
"local": "basic/goto.html"
}
},
"pascal": {
"WRITELN": {
"context_id": 3101,
"local": "pascal/writeln.html"
}
}
}Vorteil:
Editor
Compiler
GUI
F1-Hilfe
CHM
greifen auf dieselben IDs zu.
[ ] Viewer startet ohne Datei
[ ] Viewer startet mit CHM
[ ] Viewer startet mit Verzeichnis
[ ] Dark Mode färbt gesamte Anwendung
[ ] Light Mode funktioniert
[ ] Theme wird gespeichert
[ ] Theme ist beim Neustart sofort aktiv
[ ] Fensterposition speichern
[ ] Fenstergröße speichern
[ ] maximierter Zustand speichern
[ ] Splitterposition speichern
[ ] Wiederherstellung vor erstem Anzeigen
[ ] HHP lesen
[ ] HHC lesen
[ ] HHK lesen
[ ] Default Topic
[ ] SVG darstellen
[ ] relative Bilder darstellen
[ ] --topic PRINT
[ ] --word PRINT
[ ] --context-id 2101
[ ] --context-id + --topic
[ ] --keyword PRINT
[ ] --local basic/print.html
[ ] help.chm::/basic/print.html
[ ] -mapid 2101 help.chm
[ ] /context 2101 help.chm
[ ] -keyword PRINT help.chm
[ ] /topic basic/print.html help.chm
[ ] HH_HELP_CONTEXT
[ ] HH_DISPLAY_TOPIC
[ ] HH_KEYWORD_LOOKUP
[ ] hinzufügen
[ ] Doppelanlage verhindern
[ ] entfernen
[ ] Neustart
[ ] getrennte Favoriten pro CHM
Eine mögliche PyInstaller-Erzeugung:
pyinstaller ^
--noconsole ^
--onefile ^
--name chmviewer ^
chmviewer.pyBei QtWebEngine kann eine --onedir-Variante robuster sein:
pyinstaller ^
--noconsole ^
--onedir ^
--name chmviewer ^
chmviewer.pyNach dem Build sollte geprüft werden:
QtWebEngineProcess
resources
translations
platforms
PyInstaller sammelt diese Komponenten normalerweise über die Qt-Hooks ein.
Für deine Anwendung bietet sich an:
Programm.exe
chmviewer.exe
help\
c64.chm
Für Binärkompatibilität mit bereits kompilierten Anwendungen könnte später eine native DLL entstehen.
Denkbares Konzept:
alte Anwendung
│
▼
HtmlHelpW(...)
│
▼
Kompatibilitäts-DLL
│
▼
chmviewer.exe
Derzeit startet jeder Hilfeaufruf einen eigenen Prozess.
Eine spätere Erweiterung könnte:
- vorhandene Instanz erkennen
- Topic über Named Pipe / Local Socket senden
- bestehendes Fenster nach vorne holen
Mögliche Ergänzungen:
HH_DISPLAY_INDEX
HH_DISPLAY_SEARCH
HH_SET_WIN_TYPE
HH_GET_WIN_TYPE
Zusätzlich zur Kommandozeile könnte eine IPC-Schnittstelle eingeführt werden:
{
"command": "help",
"file": "c64.chm",
"topic": "PRINT",
"context_id": 2101
}Die vorhandene language-Information kann später zur Auswahl unterschiedlicher Hilfe-Dateien oder Sprachpfade erweitert werden.
chmviewer.exe help.chm --topic PRINTchmviewer.exe help.chm --topic PRINT --language basicchmviewer.exe help.chm --context-id 2101 --topic PRINTchmviewer.exe help.chm --local basic/print.htmlchmviewer.exe help.chm --keyword PRINTchmviewer.exe help.chm --word PRINTchmviewer.exe "help.chm::/basic/print.html"chmviewer.exe -mapid 2101 help.chmchmviewer.exe /context 2101 help.chmchmviewer.exe -keyword PRINT help.chmchmviewer.exe help.chm --hh-command HH_HELP_CONTEXT --hh-data 2101chmviewer.exe help.chm --hh-command HH_DISPLAY_TOPIC --hh-data basic/print.htmlchmviewer.exe help.chm --hh-command HH_KEYWORD_LOOKUP --hh-data PRINTDer CHM Viewer verbindet klassische Windows-Hilfe-Strukturen mit einer modernen QtWebEngine-basierten Darstellung.
Der entscheidende Architekturpunkt ist die Trennung zwischen:
externer Aufrufsyntax
│
▼
Normalisierung
│
▼
interne Hilfe-Anfrage
│
▼
gemeinsame Navigation
Dadurch können moderne Anwendungen und ältere Delphi-/HTML-Help-orientierte Programme dieselbe Hilfedatenbasis verwenden, ohne dass zwei getrennte Viewer gepflegt werden müssen.