FoxPro Affichage des documents
Construire un spectateur de documents à grande vitesse pour les applications FoxPro anciennes sans demander à l'application hôte de moderniser d'abord.
Plateforme
Les produits à base d'huile de coco et d'huile de coco
La pile
C++, ATL, COM, GDI, WIC, PDFium
Objectif
Affichage rapide en format des fichiers JPG, PNG et PDF
Vue d'ensemble du projet
Ce projet résout un problème commun de logiciels anciens: les utilisateurs ont besoin d'une visualisation moderne de documents à l'intérieur d'une application qui n'a jamais été conçue pour elle. Dans ce cas, l'environnement hôte est Visual FoxPro, ce qui signifie que la solution devait se comporter comme un contrôle ActiveX classique, exposer une interface COM conservatrice, rester strictement 32-bit, et éviter toute instabilité qui pourrait abattre le processus hôte.
Le résultat est FoxDocViewerIl prend en charge les formats PDF via PDFium, les formats d'images via Windows Imaging Component, et enveloppe l'ensemble du pipeline dans une interface que FoxPro peut appeler de manière fiable en utilisant des types familiers tels que BSTR, Il y a longtemps., Le double et VÉRANT.
Comment la mise en œuvre fonctionne
L'architecture est délibérément divisée en couches focalisées afin que la coquille COM reste petite et que la logique de rendu reste extensible.
1. Une coquille COM compatible avec le TERM030__
Le contrôle ActiveX est construit avec ATL et expose une double interface pour la liaison tardive et l'accès vtable. En pratique, cela signifie que FoxPro peut entraîner le spectateur avec des appels simples tels que le chargement d'une liste de documents, le déplacement entre les pages, le changement des niveaux de zoom et l'état de lecture tel que le nombre de pages ou le chemin du document actif.
Une partie subtile de la mise en œuvre est la couche d'ingestion du chemin. FoxPro peut émettre des matrices dans des formes qui ne sont pas toujours intuitives, y compris des variantes unidimensionnelles et bidimensionnelles. La sécurité les valeurs, les dériférences par variantes de référence, oblige les valeurs à des chaînes et ignore en toute sécurité les entrées inutilisables au lieu d'échouer durement.
2. Un contrôleur qui possède la navigation, le zoom et l'état
Derrière la couche ActiveX se trouve un contrôleur d'affichage dédié. Cette classe ne sait rien sur la peinture Win32 ou COM, ce qui maintient la logique propre. Elle possède le document actuel, la page actuelle, le mode de zoom, le pourcentage de zoom et le cycle de vie du cache. Le contrôle transmet les commandes dans ce contrôleur et lit les données de cadre préparées à partir de lui.
Cette séparation est importante parce qu'elle transforme un type de composant historiquement désordonné en une machine d'état prévisible.
3. Des adaptateurs de formatage pour PDF et images
Le spectateur utilise des adaptateurs séparés pour différents types de fichiers. Le décodeur JPG et PNG est géré par Windows Imaging Component, qui convertit les images en un format BGRA normalisé de 32 bits et les évolue avec l'interpolation de haute qualité de WIC. Les fichiers PDF sont gérés par PDFium, chargés dynamiquement au moment de l'exécution plutôt que liés statiquement au contrôle.
Cette stratégie de chargement dynamique est importante pour le déploiement. Pdfium.dll Si la commande est manquante, la commande fonctionne toujours pour les images et rapporte une erreur spécifique du moteur PDF lorsqu'un PDF est demandé. L'hôte reste en vie et les erreurs de déploiement apparaissent comme des rétroactions de fonctionnement récupérables au lieu d'une erreur d'enregistrement ou de démarrage cassée.
4. Render rapide par le caching et le préchargement
Les performances de rendu étaient une exigence fondamentale. L'implémentation utilise un cache de page limité le moins récemment utilisé, clés par document, page et bucket de zoom. Les valeurs de zoom sont intentionnellement aggravées en buckets afin que le cache ne s'effondre pas sur chaque petit changement de zoom. C'est l'un de ces détails qui a un effet énorme sur la vitesse perçue.
Le commandeur dispose également d'un temporiseur léger qui rend les pages adjacentes à l'avance lorsque l'interface utilisateur est inactive. Cela signifie que la page suivante ou précédente est souvent déjà chaude dans la mémoire au moment de la navigation de l'utilisateur, ce qui rend le tournage de la page immédiat même si le décoding et la rasterisation se produisent dans le code natif derrière les scènes.
5. Le dessin sans éclaboussure à l'intérieur d'un hôte hérité
La dernière étape est le moteur de rendu, qui utilise un tampon arrière hors écran et GDI devient pour peindre dans la fenêtre de contrôle sans clignotement.
Cela peut sembler de faible niveau, mais c'est exactement là que la confiance des utilisateurs est gagnée ou perdue dans le logiciel de bureau. Un spectateur qui se délecte, clignote, peint mal ou s'arrête sur la taille se sent immédiatement fragile. Cette mise en œuvre évite cela en traitant les opérations de peinture comme un pipeline contrôlé plutôt qu'une chaîne d'appels ad hoc Win32.
Les principaux défis
Faire le lien entre une version moderne et un modèle d'application ancien
L'application hôte s'attend à un comportement COM classique, pas à un navigateur intégré moderne ou à un temps d'exécution géré. Cela a exclu de nombreuses solutions faciles et a forcé la mise en œuvre à s'intégrer dans les contraintes du ActiveX, de l'hébergement à 32 bits et du cycle de vie axé sur les messages d'un contrôle traditionnel Windows.
Rendre les structures de données FoxPro prévisibles
FoxPro le comportement d'un tableau peut être étonnamment gênant lorsque les valeurs franchissent la limite COM. VÉRANT et La sécurité Le travail d'interopérabilité dans le monde réel signifiait rendre compte de la façon dont FoxPro émet réellement des matrices, et non de la façon dont une spécification COM pure le dit.
Rapidité d'équilibrage avec l'utilisation de la mémoire
Les fichiers PDF et les images haute résolution peuvent consommer rapidement la mémoire une fois rasterisés. Le cache de page utilise donc une capacité limitée avec évacuation, tandis que le zoom bucketing empêche un flot de bitmaps en cache presque identiques. L'objectif n'était pas le caching maximum à tout prix, mais une réactivité stable sous des charges de travail réalistes sur le bureau.
Échec en toute sécurité à l'intérieur du processus hôte
Un crash dur dans le spectateur serait un crash dur dans FoxPro lui-même. En raison de cela, le contrôle a été conçu pour signaler des erreurs à travers l'état et les événements, garder le vieux contenu visible si un nouveau document ne se charge pas et libérer les ressources du système déterministiquement. La stabilité n'était pas une fonctionnalité agréable à avoir; elle faisait partie de la définition du produit.
Le résultat
FoxDocViewer offre à une application commerciale ancienne une capacité moderne de visualisation de documents sans réécrire la plate-forme hôte. Les utilisateurs peuvent ouvrir des fichiers PDF et des images à l'intérieur du flux de travail existant, naviguer rapidement sur les pages, zoomer en douceur et se déplacer entre les documents avec une latence minimale.
Du point de vue de l'ingénierie, le projet est un bon exemple de modernisation pragmatique: maintenir l'interface conservatrice, isoler la logique spécifique au format, optimiser le parcours de rendu là où il est important, et considérer l'interopérabilité et la gestion des défaillances comme des problèmes de conception de première classe plutôt que des réflexions ultérieures.
Les faits saillants
Contrôle natif ActiveX pour Visual FoxPro. Intégration dynamique PDFium. Décodage d'image supporté par WIC. rendu GDI à double tampon. conception COM d'erreur qui protège le processus hôte.