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

L'impression avec Delphi


précédentsommaire

IV. L'aperçu avant impression (épisode 4)

Pour terminer cette série sur l'impression avec Delphi, 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 Delphi 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 la 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
var
 MetaFile: TMetaFile;
 MetaFileCanvas: TMetaFileCanvas;
begin
 // Création du TMetaFile
 MetaFile := TMetaFile.Create;
 { 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.}
 MetaFileCanvas := TMetaFileCanvas.Create(MetaFile, 0);
 MetaFileCanvas.TextOut(10,10,'Ce qu''on veut');
 { La libération du TMetaFileCanvas entraine le transfert des informations dans le TMetaFile}
 MetaFileCanvas.free;
 { Ici, nous pourrions sauvegarder MetaFile et obtenir ainsi notre texte }
 { sous forme de fichier wmf}
end;

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) A côté de PaintBox1, placer 2 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) Déclarer dans la section Private une variable de type TList pour contenir nos différentes pages:

 
Sélectionnez
LPages: TList;

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

 
Sélectionnez
LPages := TList.Create;

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

 
Sélectionnez
while LPages.Count > 0 do
  begin
   Dispose(LPages[0]);
   LPages.Delete(0);
  end;
LPages.Free;

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

 
Sélectionnez
var
 I, P: integer;
 S: String;
 R: TRect;

En avant pour le code ! Nous allons créer 3 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 3 pages à prévisualiser. Je vais donc ajouter directement mes 3 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 la-dite 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 I := 0 to 2 do
  begin
   LPages.add(TMetafile.Create);
   with TMetafile(LPages[I]) do
    begin
     Width  := Printer.PageWidth;
     Height := Printer.PageHeight;
    end;
  end;

A partir de là, nous allons reprendre les métafichiers 1 par 1.

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 Delphi. 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
with TMetafileCanvas.create(TMetafile(LPages[0]), 0) do begin
  Font.PixelsPerInch := P;

  font.Size := 18;
  TextOut(10, 10, 'Vous êtes sur la page 1');
  font.Size := 22;
  S := 'Ce texte est centré sur la page';
  R := Rect(0, 0, Printer.PageWidth, Printer.PageHeight);
  DrawText(handle, PChar(S), length(S), R, DT_CENTER or DT_VCENTER or DT_SINGLELINE);
  free;
 end;

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 aggrandir le TRect qui définit l'emplacement de l'ellipse.

 
Sélectionnez
with TMetafileCanvas.create(TMetafile(LPages[1]), 0) do begin
  inflateRect(R, -300, -300);
  Ellipse(R);
  Pen.Color := clBlue;
  inflateRect(R, -200, -200);
  Ellipse(R);
  Pen.Color := clGreen;
  inflateRect(R, -200, -200);
  Ellipse(R);
  Pen.Color := clRed;
  inflateRect(R, -200, -200);
  Ellipse(R);
  inflateRect(R, -200, -200);
  Rectangle(R);
  free;
 end;

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

 
Sélectionnez
I := GetDc(0);   {Obtention d'un handle de device context sur l'écran}
 with TMetafileCanvas.create(TMetafile(LPages[2]), 0) do begin
  StretchBlt(Handle,
             0,0,
             Printer.PageWidth, Printer.PageHeight,
             I,
             0,0,
             Screen.Width, Screen.Height,
             SRCCOPY);
  free;
 end;
 releaseDc(handle, I);  {ne pas oublier de relâcher le hdc}

 Prv.tag := 0;

Voilà ! Nos 3 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 quel 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
procedure TPrevisualisation.PrvPaint(Sender: TObject);
var
 M: TMetafile;
begin
if LPages.Count > 0 then
 begin
  Prv.Canvas.Brush.Color := clWhite;
  M := TMetafile(LPages[Prv.tag]);
  Prv.Canvas.FillRect(Rect(0,0, M.width, M.height)); {Pour "peindre" le fond en blanc.}
  Prv.canvas.StretchDraw(Rect(0, 0, Prv.width, Prv.Height), M);
 end;
end;

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

 
Sélectionnez
procedure TPrevisualisation.AvantClick(Sender: TObject);
begin
 if Prv.tag > 0 then
  begin
   Prv.tag := Prv.tag - 1;
   Prv.refresh;
  end
 else
  ShowMessage('Vos êtes sur la première page visible');
end;

procedure TPrevisualisation.ApresClick(Sender: TObject);
begin
 if Prv.tag < LPages.Count - 1 then
  begin
   Prv.tag := Prv.tag + 1;
   Prv.refresh;
  end
 else
  ShowMessage('Vos êtes sur la dernière page visible');
end;

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

 
Sélectionnez
procedure TPrevisualisation.lmprimerClick(Sender: TObject);
begin
 with Printer, Canvas do
  begin
   BeginDoc;
   Draw(0, 0, TMetafile(LPages[0]));
   NewPage;
   Draw(0, 0, TMetafile(LPages[1]));
   NewPage;
   Draw(0, 0, TMetafile(LPages[2]));
   EndDoc;
  end;
end;

Avec ce dernier chapitre, vous avez maintenant toutes les clés pour imprimer ce que vous voulez, avec une preview 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.

Code Delphi 5

Bonne continuation!


précédentsommaire

Ce document est issu de https://www.developpez.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.