<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Printer Pr�sentation</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- G�n�r� par Doxygen 1.3 -->
<center>
<a class="qindex" href="index.html">Page principale</a> <a class="qindex" href="namespaces.html">Liste des namespaces</a> <a class="qindex" href="hierarchy.html">Hi�rarchie des classes</a> <a class="qindex" href="classes.html">Liste par ordre alphab�tique</a> <a class="qindex" href="annotated.html">Liste des composants</a> <a class="qindex" href="files.html">Liste des fichiers</a> <a class="qindex" href="functions.html">Composants</a> </center>
<hr><h1>Printer Pr�sentation</h1>
<p>
<h2><a name="PrinterIntro"></a>
Introduction</h2>
Ce composant facilite la gestion de l'impression dans un d�veloppement C++. Il automatise l'aper�u et l'impression d'une fen�tre Windows en mode texte et en mode graphique :<p>
<ul>
<li>A partir de l'image de cette fen�tre, on obtient une impression et un aper�u graphique</li><li>A partir d'une repr�sentation des �l�ments graphiques pr�sents dans cette fen�tre, on obtient un aper�u et une impression texte.</li><li>Le composant autorise �galement la cr�ation d'un haut de page et d'un bas de page personnalis�s.</li></ul>
<p>
Le module s'appuie sur les m�canismes standards fournis par les MFC. Un effort de refactoring important a �t� fait pour faciliter l'int�gration dans le programme utilisateur.<h3><a name="PrinterIntroRappel"></a>
Rappel sur l'existant</h3>
Les programmes d�velopp�s avec les MFC b�n�ficient des services mis en place par Windows :<p>
<ul>
<li>Configuration de l'impression (bo�te de dialogue pour mise en page)</li><li>D�tection automatique des drivers de l'imprimante</li><li>Prise en compte des imprimantes distantes</li><li>Aper�u avant impression</li></ul>
<p>
La gestion de l'aper�u est une fonction complexe qui utilise la notion de p�riph�rique de sortie abstrait (device context DC). L'id�e poursuivie par les MFC est d'utiliser le m�me code pour obtenir l'impression � l'�cran ou sur l'imprimante.<p>
Le document suivant (il provient des MSDN) montre comment une classe vue doit surcharger certaines de ses m�thodes pour s'int�grer dans le canevas existant. On remarque �galement comment le contexte d'impression (classe CDC) est utilis� pour repr�senter le p�riph�rique de sortie (�cran ou imprimante). L'utilisateur dispose de cinq m�thodes pour mettre en place son code :<p>
<ul>
<li>OnPreparePrinting</li><li>OnBeginPrinting</li><li>OnPrepareDC</li><li>OnPrint</li><li>OnEndPrinting</li></ul>
<p>
Le r�le respectif de chacune des m�thodes est pr�cis� dans les commentaires du sch�ma. A chaque fois, il s'agit d'un code de bas niveau et assez complexe. Par exemple pour fonctionner avec n'importe quelle imprimante, le dessin sur le contexte d'impression doit �tre proportionnel � la taille relative disponible du p�riph�rique.<p>
<div align="center">
<img src="ArchitectureMFC.png" alt="ArchitectureMFC.png">
</div>
<p>
Enfin pour activer l'impression, il faut mettre en place les handlers d'impression en interceptant les messages ad�quats de Windows (ID_FILE_PRINT, ID_FILE_PRINT_DIRECT, ID_FILE_PRINT_PREVIEW). Au final, si l'utilisateur d�finit ses propres messages, c'est plus d'une dizaine de m�thodes qui doivent �tre r��crites (avec les cinq pr�c�dentes).<h3><a name="PrinterIntroObjectifs"></a>
Objectifs</h3>
Malgr� tout, la gestion de l'aper�u et de l'impression restent des t�ches tr�s lourdes � r�aliser. Il n'existe aucun moyen standard pour obtenir rapidement ces services. Chaque projet doit les red�velopper.<p>
L'id�e cl� de ce composant est de d�finir une classe abstraite d'impression. Elle fournit une interface compl�te pour param�trer le haut de page, le bas de page, le nom du job dans la file d'impression. Et surtout, la classe propose un 'refactoring' complet du m�canisme d'impression : Toutes les fonctions virtuelles pr�c�dentes sont 'encapsul�es' dans le composant. D�sormais les fonctions Print() et Preview() suffisent � d�rouler tout cycle d'appel.<p>
A partir de cette classe, deux classes sont sp�cialis�es. L'une CPrinterAbstract g�re une impression et un aper�u graphique. L'autre fournit les m�mes fonctionnalit�s en mode texte.<p>
Pour l'utilisateur, il suffit alors 'd'embarquer' dans son code, une instance de ces objets pour mettre en place l'impression.<h2><a name="PrinterArchi"></a>
Architecture</h2>
<h3><a name="PrinterArchiRefactoring"></a>
Refactoring</h3>
Ce premier diagramme illustre la mise en place de l'impression dans l'esprit des MFC. M�me si l'on dispose d'un objet CMyPrinter qui regroupe tout le code d'impression, il reste � surcharger les m�thodes virtuelles de la vue (sur le sch�ma on n'a repr�sent� que la premi�re et la derni�re).<p>
<div align="center">
<img src="PrintMfc.png" alt="PrintMfc.png">
</div>
<p>
Pour �viter ce travail, le composant red�finie la m�thode Print et redirige lui-m�me les appels standards sur ses propres m�thodes. Pour l'utilisateur, un seul appel � Print suffit � d�rouler le code d'impression. On obtient une meilleure isolation du code et l'int�gration est plus facile.<p>
<div align="center">
<img src="PrintRefactor.png" alt="PrintRefactor.png">
</div>
<p>
Le canevas g�n�rique de l'aper�u avant impression est r��crit dans le m�me esprit. Il est bas� sur la m�thode originale des MFC. L'id�e est de construire une application SDI simplifi�e qui vient remplacer celle en cours. Cette application utilise une vue sp�ciale CViewPrintPreview qui impl�mente les m�thodes virtuelles du canevas MFC et qui les redirige sur les m�thodes correspondantes du composant. Voici un diagramme tr�s simplifi� :<p>
<div align="center">
<img src="PreviewRefactor.png" alt="PreviewRefactor.png">
</div>
<p>
D'un autre point de vue, l'id�e g�n�rale consiste � tromper les MFC en substituant une vue pr�fabriqu�e � la vue initiale. Cette vue tr�s particuli�re code l'aper�u en exploitant le canevas standard et en redirigeant les appels sur notre propre classe qui d�tient l'impl�mentation r�elle de l'impression. Le m�canisme prend en charge la sauvegarde des �tats et des threads de Windows.<p>
<em>Ce code complexe est d�pendant de la version de Visual Studio (VC 6.0). De plus pour acc�l�rer sa cr�ation, le clone de l'application est construit avec un document vide. Il est donc impossible d'acc�der au document durant le code d'impression.</em><p>
Dans la pratique, cette limitation n'est pas g�nante : il suffit de charger les informations utiles juste avant.<h3><a name="PrinterArchiIndex"></a>
Index des classes</h3>
Ce paragraphe liste les classes de la dll et en donne une br�ve description.<p>
<ul>
<li>Les classes export�es :</li></ul>
<p>
<ul>
<li>CPrinterAbstract : Une classe abstraite qui factorise le code commun � l'impression texte et � l'impression graphique.</li><li>CPrinterHard : La classe charg�e de l'impression graphique</li><li>CPrinterTxt : Responsable de l'impression textuelle d'une fen�tre</li><li>CPrinterXcpt : La classe d�finit les exceptions susceptibles d'�tre lev�es</li><li>SDataPrint : Une structure qui contient les donn�es utiles � l'impression</li><li>CTextTable : Une table g�n�rique (plusieurs colonnes et plusieurs lignes)</li><li>CTextLineFree : Une ligne libre (plusieurs colonnes et plusieurs lignes)</li></ul>
<p>
<ul>
<li>Les classes locales � la dll</li></ul>
<p>
<ul>
<li>CDocText : Une classe repr�sentant le document texte. Il contient une liste des �l�ments � afficher</li><li>CInterfaceElement : L'interface (classe abstraite) des �l�ments de texte possibles</li><li>CTextLineEmpty : La repr�sentation d'une ligne vide</li><li>CTextTitle : Le titre d'un paragraphe</li><li>CTextData : Un doublon constitu� d'un libell� et d'une valeur</li><li>CTextList : Un adaptateur en CTextTable pour un CListCtrl</li><li>CViewPrintPreview : Une classe d'aide pour la pr�visualisation</li></ul>
<h3><a name="PrinterArchiSchema"></a>
Sch�ma de la dll</h3>
<div align="center">
<img src="UMLPrinter.png" alt="UMLPrinter.png">
</div>
<h2><a name="PrinterPrincipe"></a>
Principes</h2>
<h3><a name="PrinterPrincipeMarges"></a>
Marges, Ent�tes et bas de page</h3>
Quelque soit le type d'impression, une page comporte toujours trois parties : un ent�te, un bas de page et la page proprement dite. Pour obtenir une impression coh�rente, les marges hautes et basses doivent tenir compte du nombre de lignes occup�es par l'ent�te et le bas de page (et dans une certaine mesure, de la taille de la police). Par d�faut les marges utilis�es sont : (droite =0, haut=2, gauche=0, bas=2). L'ent�te se compose du nom du job comme titre, suivi d'une ligne de s�paration. Le bas de page comporte une ligne de s�paration, suivie � gauche du nombre de page et de la date � droite.<h3><a name="PrinterPrincipeTexte"></a>
Impression texte</h3>
L'id�e sous-jacente � l'impression texte est l'utilisation d'un document CDocText qui contient une description ligne � ligne des donn�es � afficher. Ces donn�es sont stock�es sous la forme de CFormatString ce qui leur permet de s'auto-dimensionner et de s'afficher ainsi sur plusieurs lignes. Le CDocText n'est rien d'autre qu'un tableau d'objets polymorphes qui impl�mentent l'interface minimum CInterfaceElement. La cr�ation des objets de base et le remplissage du tableau sont g�r�s via des appels aux m�thodes de CPrinterText.<p>
Le composant prend � sa charge toute la mise en page. En fonction des caract�ristiques de l'imprimante et des marges, il calcule le nombre de caract�res par ligne et le nombre de lignes par page. Il en d�duit le nombre de pages et g�re automatiquement l'aper�u et l'impression.<p>
Pour parvenir � ce r�sultat des concessions sont in�vitables. Premi�rement, tout le code se base sur la notion de <em>taille moyenne de caract�re</em>. Ceci implique que la police utilis�e est fixe. Par d�faut il s'agit de la police Times New Roman de taille 10. De plus, les �l�ments propos�s doivent �tre capable de s'auto-dimensionner sur le p�riph�rique de sortie.<p>
Par cons�quent, il n'est pas possible de d�finir un saut de page universel (en fonction de la d�finition de l'imprimante, le nombre de ligne n�cessaire pour compl�ter la page varie).<h3><a name="PrinterPrincipeGra"></a>
Impression graphique</h3>
Le principe de fonctionnement est tr�s simple : Le code recopie l'image de la fen�tre Windows dans un CBitmap (Data Dependant Bitmap ou DDB). Comme la taille de l'image d�pend du contexte, il faut ensuite cr�er un Data Independant Bitmap (DIB) pour obtenir une image capable de s'afficher � la m�me �chelle sur n'importe quel p�riph�rique. Il ne reste plus qu'� envoyer le DIB vers l'imprimante ou le presse-papier, puis � nettoyer le GDI.<h2><a name="PrinterDocText"></a>
Le document</h2>
Ce paragraphe d�crit en d�tail, les classes et les m�thodes utilis�es par le composant pour d�finir dans le document CDocText la repr�sentation textuelle de la sortie attendue. Il faut consid�rer ces classes comme un mini-langage de description des pages � imprimer.<h3><a name="PrinterDocTextEmpty"></a>
CTextEmpty</h3>
Cette classe repr�sente un saut de ligne sur le p�riph�rique de sortie. On l'ajoute tr�s facilement gr�ce � la m�thode <em>AddEmpty()</em>.<h3><a name="PrinterDocTextData"></a>
CTextData</h3>
La classe repr�sente le libell� d'un champ, suivi de sa valeur en gras. Dans l'esprit du composant, il s'agit de l'�l�ment le plus important : Une impression texte reste essentiellement une suite de libell�s et de valeurs.<p>
Pour obtenir une impression agr�able, les donn�es sont align�es sur deux abcisses qui restent fixes pour tout le document. Avant l'impression, on peut ajuster la position de ces colonnes avec la m�thode <em>SetDataColumns(int nLib, int nVal)</em>.<p>
Le libell� et la valeur s'auto-formattent dans la place qui leur est impartie. Si n�cessaire, plusieurs lignes du p�riph�riques de sortie sont utilis�es. Lorsqu'il le peut, le composant place les c�sures sur les espaces blancs de la donn�e.<p>
L'ajout d'un couple au document se fait tr�s facilement avec la m�thode <em>void AddData(LPCTSTR lpszLib, LPCTSTR lpszVal)</em>.<h3><a name="PrinterDocTextTitle"></a>
CTextTitle</h3>
Cette classe repr�sente un titre sur le p�riph�rique de sortie. Un titre comprend :<ul>
<li>Un saut de ligne</li><li>Le libell� centr� et en gras</li><li>Un saut de ligne</li></ul>
<p>
Typiquement, il sert � regrouper sous un m�me titre les libell�s et les valeurs d'un groupe de contr�les. On l'ajoute tr�s facilement gr�ce � la m�thode <em>void AddTitle(LPCTSTR lpszTitle)</em><h3><a name="PrinterDocTextList"></a>
CTextList</h3>
La classe permet de placer dans le document une liste graphique. On obtient :<ul>
<li>Un saut de ligne</li><li>Les titres des colonnes en gras</li><li>Un saut de ligne</li><li>Les donn�es de la liste.</li></ul>
<p>
Chaque �l�ment (item) est auto-formatable et est capable de s'afficher (si n�cessaire) sur plusieurs lignes du p�riph�rique de sortie. Lorsque cela se produit, les autres colonnes formatent � l'identique les �l�ments de la ligne pour maintenir un affichage coh�rent.<p>
Le formatage des colonnes et les libell�s sont r�cup�r�s directement � partir du contr�le graphique. Le facteur nPercent fournit le facteur d'�chelle entre le contr�le graphique et la sortie texte : on peut ainsi choisir d'imprimer la liste sur toute la largeur de la page. On ajoute facilement une liste au document avec la m�thode <em>AddList(CListCtrl* pList, int nPercent)</em>.<p>
Il faut noter que l'impl�mentation s'appuie sur un objet CTextTable d�crit ci-dessous.<h3><a name="PrinterDocTextTable"></a>
CTextTable</h3>
Cette classe permet de construire un tableau g�n�rique, de le remplir, puis de l'ajouter au document. Utiliser un CTextTable demande plus de travail que d'utiliser un CTextLine. Mais en contrepartie, on obtient une bien plus grande souplesse.<p>
Par rapport aux �l�ments pr�c�dents, il faut pouvoir manipuler directement l'objet pour d�finir les colonnes et ajouter les lignes. Afin d'�viter les fuites de m�moire, le module utilise une ar�ne pour construire la table. Les paragraphes suivants explicitent une utilisation r�elle de l'objet.<p>
<em> Attention : Les extraits de code doivent �tre prot�g�s par un bloc try/catch. Pour simplifier les exemples, ils ne sont pas reproduits.</em><p>
<dl compact><dt><b>Etape 1 : Cr�ation d'une table avec 2 colonnes</b></dt><dd></dd></dl>
<div class="fragment"><pre>
CTextTable* pTable = m_printerText.CreateTable(2);
pTable->SetColumn (0, 35, DT_CENTER,"Protocole :");
pTable->SetColumn (1, 35, DT_CENTER,"Longueur :");
</pre></div><p>
A noter :<ul>
<li>La cr�ation de l'objet via la fabrication de CPrinterText. En r�alit�, l'objet est cr�� sur la pile et plac� dans l'ar�ne. Le constructeur attend le nombre de colonnes.</li><li>L'initialisation des colonnes.</li></ul>
<p>
<dl compact><dt><b>Etape 2: Remplissage de la table</b></dt><dd></dd></dl>
<div class="fragment"><pre>
_AddLine(pTable, &m_EditLGMX1, &m_ComboPCLX1);
_AddLine(pTable, &m_EditLGMX2, &m_ComboPCLX2);
_AddLine(pTable, &m_EditLGMX3, &m_ComboPCLX3);
_AddLine(pTable, &m_EditLGMX4, &m_ComboPCLX4);
avec :
void
_AddLine(CTextTable* pTable, CEdit* pEdit, CComboBox* pCombo)
{
CStringArray array;
array.RemoveAll();
array.Add(pCombo->CtrlGetValue());
array.Add(pEdit->CtrlGetValue());
pTable->AddLine(array);
}
</pre></div><p>
A noter :<ul>
<li>Pour remplir une ligne de la table, on lui passe un CStringArray qui contient l'ensemble des informations.</li></ul>
<p>
<dl compact><dt><b>Etape 3 : Ajout de la table au document</b></dt><dd></dd></dl>
<div class="fragment"><pre>
m_printerText.AddTable(pTable);
</pre></div><p>
A noter :<ul>
<li>Le code ajoute la table au document texte.</li><li>En interne l'objet est retir� de l'ar�ne et le document conserve le pointeur sur cet objet.</li></ul>
<h3><a name="PrinterDocTextFreeLine"></a>
CTextFreeLine</h3>
Ce dernier type d'�l�ment permet de composer une ligne en y pla�ant un nombre variable d'informations. Ce m�canisme apporte plus de souplesse au composant. Une utilisation typique est de pouvoir afficher des donn�es qui comportent 3 ou 4 informations. Exemples d'informations :<p>
<ul>
<li>Dur�es : 3 jours</li><li>Cr�er le : 15/10/02 � 20h03</li></ul>
<p>
Dans le premier cas, on souhaite :<p>
<ul>
<li>'Dur�es :", police normale, texte align� sur les libell�s des 'data'</li><li>'3', en gras, texte align� sur les valeurs des 'data'</li><li>'jour', police normale, texte � la suite de '3'</li></ul>
<p>
Dans le second cas, on souhaite :<p>
<ul>
<li>'Cr�er le :", police normale, texte align� sur les libell�s des CData</li><li>'15/10/02', en gras, texte align� sur les valeurs des CData</li><li>'�', police normale, texte � la suite de '3'</li><li>'20h0"', en gras, texte � la suite de '�'</li></ul>
<p>
Les paragraphes suivants explicitent une utilisation r�elle de l'objet.<p>
<em> Attention : Les extraits de code doivent �tre prot�g�s par un bloc try/catch. Pour simplifier, ils ne sont pas reproduits.</em><p>
<dl compact><dt><b>Etape 1 : Cr�ation d'une ligne 'libre' </b></dt><dd></dd></dl>
<div class="fragment"><pre>
CTextFreeLine* pTextFree = m_printerText.CreateFreeLine();
</pre></div><p>
A noter :<ul>
<li>La cr�ation de l'objet via la fabrication de CPrinterText. En r�alit�, l'objet est cr�� sur la pile et plac� dans l'ar�ne.</li></ul>
<p>
<dl compact><dt><b>Etape 2: Remplissage de la ligne</b></dt><dd></dd></dl>
<div class="fragment"><pre>
pTextFree->Add("Une", 3, true);
pTextFree->Add("Ligne", 20, false);
pTextFree->Add("'libre'", 40, true);
</pre></div><p>
A noter :<ul>
<li>On remplit la ligne avec la m�thode Add. On lui passe le libell�, la position et un bool�en qui indique si le texte est normal ou en gras.</li><li>Une ligne libre ne tient que sur une seule ligne ! Il n'y a pas de contr�le, ni d'ajustement possible. Si le texte est trop long, il sera tronqu�.</li></ul>
<p>
<dl compact><dt><b>Etape 3 : Ajout de la ligne</b></dt><dd></dd></dl>
<div class="fragment"><pre>
m_textPrinter.AddFreeLine(pTextFree);
</pre></div><p>
A noter :<ul>
<li>Le code ajoute la ligne au document texte.</li><li>En interne l'objet est retir� de l'ar�ne et le document conserve le pointeur sur cet objet.</li></ul>
<h2><a name="PrinterSources"></a>
Sources</h2>
La dll printer simplifie l'impression texte et l'impression graphique d'une fen�tre Windows. Il s'agit d'une dll r�guli�re au sens MFC qui ne propose aucun contr�le �tendu, mais qui prend en charge une partie du canevas MFC de l'impression.<p>
Printer est situ� dans l'environnement de d�veloppement sous le r�pertoire $Devp\Sources\Printer. Voici sa structure :<p>
<ul>
<li><b>Sources</b> : contient le source de la dll.</li><li><b>Doc</b> : Le projet Doxygen pour la documentation.</li><li><b>Test</b> : Un exemple d'utilisation.</li></ul>
<p>
<div align="center">
<img src="PrinterPath.png" alt="PrinterPath.png">
</div>
<p>
Le projet inclut des options de post-compilation qui recopie automatiquement les .lib et .dll sous les r�pertoires standards de l'environnement : $Devp\Lib & $Devp\Bin. En mode debug, on obtient les fichiers PrinterD.lib & PrinterD.dll, en mode release, on obtient les fichiers Printer.lib et Printer.dll.<p>
Le projet printer, comprend �galement le fichier "printer.h" situ� sous $Devp\Include. Inclure ce fichier dans un source permet d'obtenir toute les d�clarations n�cessaires.<p>
Enfin l'ensemble du code est plac� dans le namespace printer. Pour utiliser les composants du module il suffit d'importer le namespace (instruction <em>using namespace printer;</em>) ou d'utiliser le nom qualifi� (exemple <em><a class="el" href="classprinter_1_1CPrinterText.html">printer::CPrinterText</a> printerText;</em>).<h2><a name="PrinterUsage"></a>
Usage</h2>
Le projet montre une utilisation du composant. L'impression et l'aper�u graphique sont r�alis�s avec CPrinterHard original. On obtient alors les hauts et les bas de page d�finis par d�faut.<p>
Pour les m�mes fonctionnalit�s en mode texte, une version personnalis�e de CPrinterText est utilis�e. Ceci se fait simplement en surchargeant les m�thodes <em>PrintPageHeader</em> et <em>PrintPageFooter</em> dans une classe d�riv�e.<p>
L'autre point int�ressant du projet est qu'il montre comment automatiser le remplissage du document texte � partir du contenu d'une fen�tre graphique. L'id�e est de confier l'analyse � une classe 'Fabrication' qui va lire un � un le contenu des contr�les. Pour cela il est n�cessaire d'activer la RTTI et de conc�der une r�gle de nommage sur les contr�les 'GROUP'.<p>
Evidemment, la classe fournie ici est embryonnaire. Elle ne reconna�t que quelques types de contr�le et ne permet pas une lecture partielle de la vue. Mais il est assez facile de l'am�liorer.<h3><a name="PrinterUsageRes"></a>
Ressource</h3>
Le menu est modifi� afin de pr�senter les options suivantes :<p>
<ul>
<li>Fichier<ul>
<li>Imprimer Texte ID_FILE_PRINT_TEXT</li><li>Imprimer Ecran ID_FILE_PRINT_GRA</li><li>Aper�u<ul>
<li>Aper�u Texte ID_FILE_PREVIEW_TEXT</li><li>Aper�u Ecran ID_FILE_PREVIEW_GRA</li></ul>
</li></ul>
</li></ul>
<h3><a name="PrinterUsageTestDocH"></a>
TestDoc.h</h3>
On place dans le document les instances des objets d'impression. Le mode permet de distinguer l'impression graphique de l'impression texte.<p>
<div class="fragment"><pre>
...
// Attributes
public:
enum Mode {PRINTER_TEXT, PRINTER_GRA};
void SetMode(Mode mode);
void PrinterPreview();
void PrinterPrint();
void CreateDocText(CTestView* pView);
void InitPrinter();
...
private :
CPrinterHard m_hardPrinter;
CMyPrinter m_textPrinter;
Mode m_nMode;
</pre></div><h3><a name="PrinterUsageTestDocCpp"></a>
TestDoc.cpp</h3>
La m�thode SetMode permet de changer le type d'impression. Il est n�cessaire de conserver cette information � cause du m�canisme de la pr�visualisation. Le code de PrinterPrint et PrinterPreview est tr�s classique. Il faut noter que les exceptions CPrinterXcpt sont intercept�es (c'est indispensable).<p>
<div class="fragment"><pre>
void
CTestDoc::SetMode(Mode mode)
{
m_nMode = mode;
}
void
CTestDoc::PrinterPrint()
{
try {
switch (m_nMode) {
case PRINTER_TEXT :
m_textPrinter.Print();
break;
case PRINTER_GRA :
m_hardPrinter.Print();
break;
default:
ASSERT(FALSE);
}
}
catch (CPrinterXcpt& xcpt) {
AfxMessageBox( xcpt.GetErrorMsg() );
}
}
void
CTestDoc::PrinterPreview()
{
try {
switch (m_nMode) {
case PRINTER_TEXT :
m_textPrinter.Preview();
break;
case PRINTER_GRA :
m_hardPrinter.Preview();
break;
default:
ASSERT(FALSE);
}
}
catch (CPrinterXcpt& xcpt) {
AfxMessageBox( xcpt.GetErrorMsg() );
}
}
</pre></div><p>
La m�thode suivante initialise les objets charg�s de l'impression. A cause de la d�finition de bas de page et de haut de page personnalis�s, il faut ajuster les marges de l'impression texte.<p>
Il est important de passer � la m�thode SetWindow, l'adresse valide de la fen�tre. Dans le cas de la vue, ceci ne peut �tre accompli qu'� partir du OnInitialUpdate.<p>
Enfin, on fixe le message du job dans la file d'impression de Windows. <div class="fragment"><pre>
void
CTestDoc::InitPrinter()
{
m_textPrinter.SetMargins(0,6,0,3);
m_hardPrinter.SetWindow(AfxGetMainWnd());
m_hardPrinter.SetTitleDoc("Test Impression graphique");
m_textPrinter.SetWindow(AfxGetMainWnd());
m_textPrinter.SetTitleDoc("Test Impression texte");
}
</pre></div><p>
La derni�re m�thode initialise le document texte avec les informations de la vue. On remarque l'utilisation de la classe CFacteur pour un remplissage automatique du document.<p>
Le code montre �galement comment ajouter un texte libre. Il faut bien r�aliser que tout ce qui est plac� sur le p�riph�rique de sortie, n'a pas forc�ment une existence physique dans la fen�tre...<p>
<div class="fragment"><pre>
void
CTestDoc::CreateDocText(CTestView* pView)
{
try {
// Partir d'un document propre
m_textPrinter.ClearDoc();
// Ajouts automatique
CFacteur facteur;
facteur.Analyser(pView, &m_textPrinter);
//
// On peut ajouter des valeurs autres...
//
m_textPrinter.AddTitle("Ajouts libres....");
// On ajoute une ligne libre
CTextFreeLine* pTextFree = m_textPrinter.CreateFreeLine();
pTextFree->Add("Un", 3, true);
pTextFree->Add("exemple", 20, false);
pTextFree->Add("de ligne", 40, true);
pTextFree->Add("libre.", 70, false);
m_textPrinter.AddFreeLine(pTextFree);
}
catch (CPrinterXcpt& xcpt) {
AfxMessageBox( xcpt.GetErrorMsg() );
}
}
</pre></div><h3><a name="PrinterUsageTestViewh"></a>
TestView.h</h3>
Le fichier "Printer.h" (sous $Devp\Include) permet d'obtenir toutes les d�clarations n�cessaires. On d�clare aussi les handlers pour ces messages et ceux des MFC. Les instances de CPrinterHard et CMyPrinter sont d�tenues par le document.<p>
<div class="fragment"><pre>
class CTestView : public CFormView
{
...
// Generated message map functions
protected:
//{{AFX_MSG(CTestView)
afx_msg void OnFilePrintPreviewText(); // ID_FILE_PREVIEW_TEXT (dll)
afx_msg void OnFilePrintPreviewGra(); // ID_FILE_PREVIEW_GRA (dll)
afx_msg void OnFilePrintGra(); // ID_FILE_PRINT_GRA (dll)
afx_msg void OnFilePrintText(); // ID_FILE_PRINT_TEXT (dll)
afx_msg void OnFilePrintPreview(); // ID_FILE_PREVIEW (standard mfc)
afx_msg void OnFilePrint(); // ID_FILE_PRINT (standard mfc)
//}}AFX_MSG
</pre></div><h3><a name="PrinterUsageTestViewCpp"></a>
TestView.cpp</h3>
La table des messages reprend la d�finition des menus (branchement des commandes d'impression sur les handlers). Elle comporte des entr�es � la fois pour les commandes du menu et aussi pour le canevas MFC (ID_FILE_PRINT, ID_FILE_PRINT_DIRECT, ID_FILE_PRINT_PREVIEW). L'impl�mentation est tr�s simple : OnFilePrint et OnFilePrintPreview font le travail en redirigeant l'appel sur la bonne impression. Les handlers sp�cifiques du menu, ne font que mettre � jour le mode, et rediriger l'appel sur OnFilePrint et OnFilePrintPreview.<p>
Les exceptions sont capt�es dans les m�thodes du document.<p>
<div class="fragment"><pre>
BEGIN_MESSAGE_MAP(CTestView, CFormView)
//{{AFX_MSG_MAP(CTestView)
ON_COMMAND(ID_FILE_PRINT_PREVIEW_TEXT, OnFilePrintPreviewText )
ON_COMMAND(ID_FILE_PRINT_PREVIEW_GRA, OnFilePrintPreviewGra)
ON_COMMAND(ID_FILE_PRINT_TEXT, OnFilePrintText)
ON_COMMAND(ID_FILE_PRINT_GRA, OnFilePrintGra)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, OnFilePrint)
ON_COMMAND_EX(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
END_MESSAGE_MAP()
....
/////////////////////////////////////////////////////////////////////////////
// Impression MFC standard
// Les Fcts sont INDISPENSABLES pour pouvoir Imprimer � partir de la Pr�visualisation.
/////////////////////////////////////////////////////////////////////////////
void CTestView::OnFilePrint()
{
GetDocument()->PrinterPrint();
}
void CTestView::OnFilePrintPreview()
{
GetDocument()->PrinterPreview();
}
/////////////////////////////////////////////////////////////////////////////
// Branchement de l'impression sur le cannevas
// On utilise un 'mode' pour discriminer les choix possibles
/////////////////////////////////////////////////////////////////////////////
void CTestView::OnFilePrintPreviewText()
{
GetDocument()->SetMode(CTestDoc::PRINTER_TEXT);
GetDocument()->CreateDocText(this);
OnFilePrintPreview();
}
void CTestView::OnFilePrintText()
{
GetDocument()->SetMode(CTestDoc::PRINTER_TEXT);
GetDocument()->CreateDocText(this);
OnFilePrint();
}
void CTestView::OnFilePrintPreviewGra()
{
GetDocument()->SetMode(CTestDoc::PRINTER_GRA);
OnFilePrintPreview();
}
void CTestView::OnFilePrintGra()
{
GetDocument()->SetMode(CTestDoc::PRINTER_GRA);
OnFilePrint();
}
// Un raccourci pour le test
void CTestView::OnButton1()
{
OnFilePrintPreviewText();
}
</pre></div><h2><a name="Credits"></a>
Cr�dits</h2>
MSDN : print & preview<p>
Mac Graven : a sample "How to make a WYSIWYG hardcopy" in CodeGuru<p>
Chris Maunder : a sample "Printing without the DocText/View framework" in CodeGuru<p>
Koay Kah Hoe : a sample "Print Previewing without the DocText/View Framework" in CodeProject<hr><address style="align: right;"><small>G�n�r� le Fri Oct 31 11:09:00 2003 pour Printer par
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0
width=110 height=53></a>1.3 </small></address>
</body>
</html>