IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Impression Avec C++ Builder


précédentsommairesuivant

IV. L'impression avec C++ Builder (épisode 4)

Pour terminer cette série sur l'impression avec C++ Builder, nous allons voir comment réaliser un aperçu avant impression. Il existe beaucoup de composants (gratuits ou pas) qui permettent ce genre de chose. Il en est un que j'affectionne particulièrement et qui s'appelle TMWPrintObject. Il a été développé par . N'hésitez pas à lui réclamer (en anglais) la dernière version avec l'exemple qui l'accompagne, c'est en freeware et très bien fait. Pensez juste à lui dire que je vous ai parlé de lui, il verra que j'ai tenu parole :-). Mais là n'est pas notre propos d'aujourd'hui.

Avant toute chose, il nous faut parler des objets TMetafile et TMetafileCanvas. Ce sera la base de notre étude.

TMetafile est un objet C++ Builder qui facilite la création d'un métafichier. Cet objet graphique pourra être sauvegardé sous forme de fichier et importé dans tout logiciel acceptant le format WMF. Cela nous offrira la possibilité de sauvegarder une (ou plusieurs) page de notre état pour une réutilisation ultérieure.

Le TMetafile ne possédant pas de Canvas pour dessiner, nous devrons utiliser un TMetafileCanvas.

La technique va consister en la création d'autant de métafichiers que de pages à imprimer. Chaque page étant devenue un fichier WMF, il nous sera alors possible de transférer chaque fichier-page soit sur le canvas de l'imprimante, soit sur n'importe quel canvas. Un simple transfert avec BitBlt ou StretchBlt nous permettra une redirection de nos commandes d'impression sur l'objet de notre choix.

Un TMetafile étant un objet comme les autres, nous stockerons les diverses pages dans un TList. Notre TList sera donc notre liste de pages à imprimer.

Schématisons ce raisonnement :

Image non disponible

Comment fonctionne TMetafileCanvas ?

La création d'un TMetafileCanvas passe d'abord par la création d'un TMetafile. Ensuite TMetafileCanvas sera utilisé comme n'importe quel TCanvas. L'utilisation de cet objet se fait de la manière suivante :

 
Sélectionnez
// Création du TMetaFile
 TMetafile *pMetafile = new TMetafile;
 // Création du TMetaFileCanvas en utilisant le TMetaFile comme paramètre.
 // Cela indique à Delphi que tout ce qui sera envoyé à destination du canvas 
 // devra passer dans le TMetaFile.
 TMetafileCanvas *pCanvas = new TMetafileCanvas(pMetafile, 0);
 MetaFileCanvas->TextOut(10,10, "Ce qu'on veut ");
 // La libération du TMetaFileCanvas entraine le transfert des informations dans le TMetaFile
 delete pMetafile;
 // Ici, nous pourrions sauvegarder MetaFile et obtenir ainsi notre texte 
 // sous forme de fichier wmf

Nous allons réunir tous les éléments que nous connaissons afin de créer un PrintPreview simple.

Lors de sa création, notre métafichier pourra prendre la dimension voulue en pixels par ses propriétés Width et Height. Notre aperçu avant impression utilisera un TPaintBox placé sur notre TForm. Il serait également possible d'utiliser un TImage pour profiter de la persistance de l'affichage, mais les performances seront meilleures en terme de rapidité et de ressources utilisées. Il faudra donc que le programme redessine la page en cours d'affichage à chaque événement OnPaint du composant. Allons-y !

1) Créez un nouveau projet et nommez la feuille principale Previsualisation.

2) Placez un composant TPaintBox (onglet Système) en haut à gauche de votre Form. Définissez ses propriétés comme suit:

Name = « Prv »; Top = 10; Left = 10; Height = 594; Width = 420; // format A4 = 210 * 297 mm --> 420 * 594 pixels.

3) À côté de PaintBox1, placez deux boutons de commandes respectivement Avant et Après pour les propriétés name de chacun.

Votre feuille devrait ressembler à ceci :

Image non disponible

4) Nous allons utiliser un Objet de type TList pour contenir nos différentes pages, nous le nommerons Lpages.

5) Ajouter le code suivant dans l'événement OnCreate de votre feuille :

 
Sélectionnez
TMetafile *pMetafile;
 TMetafileCanvas *pCanvas;
 TList *LPages = new TList();

6) Ajouter le code suivant dans l'événement OnDestroy de votre feuille (libération des ressources utilisées) :

 
Sélectionnez
void __fastcall TForm1::FormDestroy(TObject *Sender)
 {
 for(int i = 0; i <= LPages->Count - 1; i++)
  {
   delete (TMetafile *)LPages->Items[i];
  }
 LPages->Clear();
 delete LPages;
 }

À présent, nous allons ajouter du code à l'événement OnCreate de notre feuille :

 
Sélectionnez
void __fastcall TForm1::FormCreate(TObject *Sender)
 {
 TRect R;
 String S;
 int P;

En avant pour le code ! Nous allons créer trois pages à ajouter au TList LPages. La première page contiendra du texte simple, la seconde des tracés graphiques et la dernière une image. Tout va se passer dans l'événement OnCreate de notre feuille de prévisualisation.

Pour commencer, nous allons stocker la valeur indiquant le nombre pixels dans un pouce (souvenez-vous que pour l'imprimante, la valeur est la même en x et en y). Cette valeur va nous servir plusieurs fois, et j'ai donc jugé opportun de la stocker dans une variable.

 
Sélectionnez
P = GetDeviceCaps(Printer()->Handle, LOGPIXELSX);

Pour cet exemple, je sais déjà qu'il y aura trois pages à prévisualiser. Je vais donc ajouter directement mes trois métafichiers à ma liste LPages. Ici, on ne peut pas utiliser une variable locale, car vous le savez, une variable locale à une procédure a une durée de vie égale à celle de ladite procédure. Je vais donc utiliser une méthode de création directement sous forme de paramètre à la fonction add de mon TList. Pour chaque métafichier, il faut indiquer une largeur et une hauteur en utilisant les propriétés Width et Height. Comme chaque métafichier est destiné à être imprimé sur un canvas d'imprimante, je vais initialiser la largeur de chaque métafichier avec Printer.PageWidth et la hauteur avec Printer.PageHeight.

 
Sélectionnez
for(int I = 0; I <=2; I++)
  {
   pMetafile = new TMetafile;
   pMetafile->Width = Printer()->PageWidth;
   pMetafile->Height = Printer()->PageHeight;
   LPages->Add(pMetafile);
  }

À partir de là, nous allons reprendre les métafichiers un par un.

Pour chacun, nous allons créer un canvas Sur le premier canvas, écrivons un texte en haut à gauche avec la méthode Canvas.TextOut et un texte centré avec l'API DrawText.

ATTENTION: ici, une chose très importante. Il est indispensable, pour obtenir un aperçu correct des impressions texte, de modifier la propriété PixelsPerInch du canvas. En effet, lors de la copie sur le canvas du PaintBox, il en sera tenu compte par C++ Builder. Quand vous aurez terminé l'écriture de ce code, faites l'essai en mettant cette ligne en commentaire et visualisez le résultat.

 
Sélectionnez
pCanvas = new TMetafileCanvas((TMetafile *)LPages->Items[0], 0);
 // écriture d'une premiere chaine
 pCanvas->Font->PixelsPerInch = P;
 pCanvas->Font->Size = 18;
 pCanvas->TextOut(10, 10, "Vous etes sur la page 1");
 // écriture d'une seconde chaine
 pCanvas->Font->Size = 22;
 S = "Ce texte est centré sur la page";
 R = Rect(0, 0, Printer()->PageWidth, Printer()->PageHeight);
 DrawText(pCanvas->Handle, S.c_str(),S.Length(), &R, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
 delete pCanvas;

Sur la seconde page, je vais dessiner un rectangle et plusieurs ellipses imbriquées avec des couleurs différentes. L'API InflateRect utilisée permet de réduire ou agrandir le TRect qui définit l'emplacement de l'ellipse.

 
Sélectionnez
pCanvas = new TMetafileCanvas((TMetafile *)LPages->Items[1], 0);
 InflateRect(&R, -300, -300);
 pCanvas->Ellipse(R);
 pCanvas->Pen->Color = clBlue;
 InflateRect(&R, -200, -200);
 pCanvas->Ellipse(R);
 pCanvas->Pen->Color = clGreen;
 InflateRect(&R, -200, -200);
 pCanvas->Ellipse(R);
 pCanvas->Pen->Color = clRed;
 InflateRect(&R, -200, -200);
 pCanvas->Ellipse(R);
 InflateRect(&R, -200, -200);
 pCanvas->Rectangle(R);
 delete pCanvas;

Pour terminer, nous allons capturer l'écran du PC et l'afficher au centre de la page.

 
Sélectionnez
HDC I;
 I = GetDC(0); // Obtention d'un handle de device context sur l'écran
 pCanvas = new TMetafileCanvas((TMetafile *)LPages->Items[2], 0);
 StretchBlt(pCanvas->Handle, 0, 0,
             Printer()->PageWidth, Printer()->PageHeight,
             I, 0, 0,
             Screen->Width, Screen->Height,
             SRCCOPY);
 ReleaseDC(Handle, I); // ne pas oublier de relâcher le HDC
 Prv->Tag = 0;
 delete pCanvas;

Voilà ! Nos trois pages sont créées. Il s'agit maintenant de gérer l'affichage. Cela va se faire naturellement par l'événement OnPaint du TPaintBox. Pour savoir quelle page doit s'afficher, nous allons utiliser la propriété tag du PaintBox. Si tag est égal à 2, le PaintBox affichera l'élément 2 du TList LPages.

 
Sélectionnez
void __fastcall TForm1::PrvPaint(TObject *Sender)
 {
 if(LPages->Count > 0)
  {
   Prv->Canvas->Brush->Color = clWhite;
   pMetafile = (TMetafile *)LPages->Items[Prv->Tag];
   Prv->Canvas->FillRect(Rect(0,0, pMetafile->Width, pMetafile->Height)); //Pour "peindre" le fond en blanc.
   Prv->Canvas->StretchDraw(Rect(0, 0, Prv->Width, Prv->Height), pMetafile);
  }
 }

Il ne reste plus qu'à coder les événements OnClick des boutons Avant et Arrière

 
Sélectionnez
void __fastcall TForm1::AvantClick(TObject *Sender)
 {
 // avant
 if(Prv->Tag > 0)
  {
   Prv->Tag = Prv->Tag - 1;
   Prv->Refresh();
  }
 else
  {
   Prv->Refresh();
   ShowMessage(" Vos êtes sur la première page visible ");
  }
 }
 
 //--------------------------------------------------------------------------- 
 void __fastcall TForm1::ApresClick(TObject *Sender)
 {
 // apres
 if(Prv->Tag < LPages->Count - 1)
  {
   Prv->Tag = Prv->Tag + 1;
   Prv->Refresh();
  }
 else
  {
   Prv->Refresh();
   ShowMessage(" Vos êtes sur la dernière page visible ");
  }
 }

Et c'est tout ! Alors ? Compliqué ? Vous voyez que non ! Pour terminer, vous ajouterez la commande d'impression qui sera tout simplement :

 
Sélectionnez
void __fastcall TForm1::ImprimerClick(TObject *Sender)
 {
 // imprimer
 Printer()->BeginDoc();
 Printer()->Canvas->Draw(0, 0, (TMetafile *)LPages->Items[0]);
 Prv->Tag = 0;
 Prv->Refresh();
 Sleep(1000);
 Printer()->NewPage();
 Printer()->Canvas->Draw(0, 0, (TMetafile *)LPages->Items[1]);
 Prv->Tag = 1;
 Prv->Refresh();
 Sleep(1000);
 Printer()->NewPage();
 Printer()->Canvas->Draw(0, 0, (TMetafile *)LPages->Items[2]);
 Prv->Tag = 2;
 Prv->Refresh();
 Sleep(1000);
 Printer()->EndDoc();
 }

Avec ce dernier chapitre, vous avez maintenant toutes les clés pour imprimer ce que vous voulez, avec une prévisualisation personnalisée à votre convenance. Vous pouvez même sauvegarder vos états de sortie sous forme de fichier Wmf pour une réimpression ultérieure facile.

Bonne continuation !


précédentsommairesuivant

Ce document est issu de http://www.développez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.