Comment est-ce que je fais l’aperçu avant impression dans win32 c ++?

J’ai une fonction de dessin qui prend juste un HDC. Mais je dois montrer une version à l’échelle EXACT de ce qui sera imprimé.

Donc, actuellement, j’utilise CreateCompatibleDC () avec une imprimante HDC et CreateCompatibleBitmap () avec le HDC de l’imprimante.

Je pense que le DC aura la largeur et la hauteur exactes de l’imprimante. Et lorsque je sélectionne des fonts dans ce HDC, le texte sera mis à l’échelle exactement comme le ferait l’imprimante.

Malheureusement, je ne peux pas utiliser StretchBlt () pour copier les pixels de ce HDC sur le HDC du contrôle car ils sont de différents types HDC, je suppose.

Si je crée le “canevas de mémoire” à partir d’une fenêtre HDC avec le même nom que la page de l’imprimante, les fonts s’affichent depuis qu’elles sont mises à l’échelle pour l’écran, pas pour la page …

Dois-je créerCompatibleDC () à partir du DC de la fenêtre et de CreateCompatibleBitmap () à partir du contrôleur de domaine de l’imprimante ou de quelque chose?

Si quelqu’un pouvait expliquer la bonne façon de le faire. (Et toujours quelque chose qui ressemble EXACTEMENT à l’imprimante) …

Eh bien, je l’apprécierais !!

… Steve

En fonction de votre précision, cela peut être difficile.

Il y a beaucoup d’approches. On dirait que vous essayez de dessiner sur un bitmap de la taille d’une imprimante puis de le réduire. Les étapes à suivre sont les suivantes:

  1. Créez un contrôleur de domaine (ou mieux encore, un contexte d’information) pour l’imprimante.
  2. Interrogez l’imprimante DC pour connaître la résolution, la taille de la page, les décalages physiques, etc.
  3. Créez un contrôleur de domaine pour la fenêtre / l’écran.
  4. Créez un DC compatible (le DC de mémoire).
  5. Créez un bitmap compatible pour la fenêtre / l’écran, mais la taille doit correspondre à la taille de pixel de la page de l’imprimante. (Le problème avec cette approche est que c’est un bitmap énorme et il peut échouer.)
  6. Sélectionnez le bitmap compatible dans la mémoire DC.
  7. Dessinez à la mémoire DC, en utilisant les mêmes coordonnées que vous utiliseriez si vous dessinez sur l’imprimante réelle. (Lorsque vous sélectionnez des fonts, assurez-vous de les mettre à l’échelle du pouce logique de l’imprimante, et non du pouce logique de l’écran.)
  8. StretchBlt la mémoire DC à la fenêtre, ce qui réduira l’image entière. Vous voudrez peut-être expérimenter le mode étirement pour voir ce qui fonctionne le mieux pour le type d’image que vous allez afficher.
  9. Libérer toutes les ressources.

Mais avant de vous diriger dans cette direction, considérez les alternatives. Cette approche implique l’allocation d’un bitmap hors écran ÉNORME. Cela peut échouer sur les ordinateurs pauvres en ressources. Même si ce n’est pas le cas, il se peut que vous affamiez d’autres applications.

L’approche de métafichier donnée dans une autre réponse est un bon choix pour de nombreuses applications. Je commencerais avec ça.

Une autre approche consiste à déterminer toutes les tailles dans une unité fictive haute résolution. Par exemple, supposons que tout se trouve dans un millième de pouce. Ensuite, vos routines de dessin adapteront cette unité imaginaire à la résolution réelle utilisée par le périphérique cible.

Le problème avec cette dernière approche (et probablement le métafichier) est que les fonts GDI ne sont pas parfaitement linéaires. La largeur des caractères individuels est modifiée en fonction de la résolution cible. Sur un périphérique haute résolution (comme une imprimante laser 300+ ppp), ce réglage est minime. Mais sur un écran de 96 ppp, les réglages peuvent entraîner une erreur significative sur la longueur d’une ligne. Le texte dans la fenêtre d’aperçu peut donc sembler hors de proportion (généralement plus large) que sur la page imprimée.

Ainsi, l’approche hardcore consiste à mesurer le texte dans le contexte de l’imprimante et à mesurer à nouveau dans le contexte de l’écran, et à ajuster la différence. Par exemple (à l’aide de numéros composés), vous pouvez mesurer la largeur d’un texte dans le contexte de l’imprimante et obtenir 900 pixels d’imprimante. Supposons que le rapport entre les pixels de l’imprimante et les pixels de l’écran soit de 3: 1. Vous vous attendez à ce que le même texte à l’écran soit de 300 pixels d’écran. Mais vous mesurez dans le contexte de l’écran et vous obtenez une valeur comme 325 pixels d’écran. Lorsque vous dessinez sur l’écran, vous devez en quelque sorte réduire le texte de 25 pixels. Vous pouvez rapprocher les caractères, ou choisir une police légèrement plus petite, puis les étirer.

L’approche hardcore implique plus de complexité. Vous pouvez, par exemple, essayer de détecter les substitutions de fonts effectuées par le pilote d’imprimante et les faire correspondre le plus possible aux fonts d’écran disponibles.

J’ai eu de la chance avec un hybride du big bitmap et des approches hardcore. Au lieu de créer un bitmap géant pour toute la page, j’en fais un assez grand pour une ligne de texte. Ensuite, je dessine à la taille de l’imprimante pour le bitmap hors écran et StretchBlt jusqu’à la taille de l’écran. Cela élimine les problèmes de taille en cas de légère dégradation de la qualité de la police. Il convient à l’aperçu avant impression réel, mais vous ne souhaitez pas créer un éditeur WYSIWYG comme celui-ci. Le bitmap à une ligne est suffisamment petit pour que cela soit pratique.

La bonne nouvelle est que le texte est difficile. Tout autre dessin est une simple mise à l’échelle des coordonnées et des tailles.

Je n’ai pas beaucoup utilisé GDI +, mais je pense qu’il a éliminé la mise à l’échelle non linéaire des fonts. Donc, si vous utilisez GDI +, il vous suffit de mettre vos coordonnées à l’échelle. L’inconvénient est que je ne pense pas que la qualité de la police sur GDI + soit aussi bonne.

Et enfin, si vous êtes une application native sur Vista ou une version ultérieure, assurez-vous d’avoir marqué votre processus comme ” DPI-aware “. Sinon, si l’utilisateur se trouve sur un écran à haute résolution, Windows vous mentira et affirmera que la résolution n’est que de 96 ppp, puis effectuez une mise à l’échelle floue de ce que vous dessinez. Cela dégrade la qualité visuelle et rend le débogage de votre aperçu avant impression encore plus compliqué. Étant donné que de nombreux programmes ne s’adaptent pas bien aux écrans DPI supérieurs, Microsoft a ajouté par défaut une “mise à l’échelle en haute résolution” à partir de Vista.

Edité pour append

Une autre mise en garde: si vous sélectionnez un HFONT dans la mémoire DC avec le bitmap de la taille de l’imprimante, il est possible que vous obteniez une police différente de celle obtenue lors de la sélection de ce même HFONT dans le DC de l’imprimante. Cela est dû au fait que certains pilotes d’imprimante remplacent les fonts communes par celles en mémoire. Par exemple, certaines imprimantes PostScript substituent une police PostScript interne à certaines fonts TrueType courantes.

Vous pouvez d’abord sélectionner le HFONT dans le CI d’imprimante, puis utiliser les fonctions GDI comme GetTextFace , GetTextMesortingcs et peut-être GetOutlineTextMesortingcs pour connaître la police sélectionnée. Ensuite, vous pouvez créer un nouveau LOGFONT pour essayer de mieux correspondre à ce que l’imprimante utilisera, le transformer en HFONT et le sélectionner dans votre mémoire DC. C’est la marque d’une très bonne implémentation.

Une chose qui pourrait être utile d’essayer est de créer un métafichier DC amélioré, de le dessiner normalement, puis de mettre à l’échelle ce métafichier à l’aide de mésortingques d’imprimante. C’est l’approche utilisée par l’exemple de WTL BmpView – Je ne sais pas à quel point cela sera précis, mais cela pourrait être intéressant (il devrait être facile de porter les classes pertinentes sur Win32, mais WTL est un excellent substitut pour la programmation Win32). pourrait être utile d’utiliser.)

Eh bien, ce ne sera pas la même chose car vous avez une résolution plus élevée dans l’imprimante DC, vous devrez donc écrire une sorte de fonction de conversion. Je voudrais aller avec la méthode que vous avez à travailler, mais le texte était trop petit et il suffit de multiplier chaque position / taille de police par la largeur de la fenêtre de l’imprimante et diviser par la largeur de la fenêtre source.