Impression d'un Form

cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015 - 9 août 2011 à 11:18
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015 - 25 août 2011 à 11:53
Christian
Bonjour,
Je viens de créer un petit programme qui représente différentes images dans une form, cette forme a la dimension d'une feuille A4 et lorsque j'envoie l'impression avec l'ordre "Form1.Print;" sous Delphi 7, l'impression correspond a l'image affiché sur l'écran celle-ci se trouve tronquée et il me manque la parti basse.
Ma question comment faire pour obtenir l'impression total de la form complète quelque soit l'écran utilisé ?
Merci de votre attention.
PS je suis débutant dans Delphi 7.

25 réponses

Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
9 août 2011 à 16:45
Salut,

[quote= Caribensila]Et en passant par GetFormImage ? /quote
non ça ne fonctionne pas

si tu veux faire une image d'une fiche qui est partiellement recouverte ou qui se trouve en dehors de l'écran il faut utiliser PrintWindow:

l'exemple est un peu idiot mais il est fonctionnel.

Il faut:
1 TImage
1 TButton
1 TTimer

et compléter le code comme suit:
[hr]

unit  UPrintWindowMain;

[b]interface

uses
  /bWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

[b]type
  /bTForm10  = class(TForm)
    ScrollBox1: TScrollBox;
    Image1: TImage;
    Button1: TButton;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  [b]private
    /b { Déclarations privées }
  [b]public
    /b{ Déclarations publiques }
  end;

function PrintWindow(ahwnd: HWND; hdcBlt: HDC; nFlags: UINT): Bool; stdcall;
external 'User32.dll' name 'PrintWindow';

[b]var
  /bForm10: TForm10;

[b]implementation

/b{$R *.dfm}
// ATTENTION cette fonction crée un TBitmap c'est à vous de le libérer à la fin
function DoShot(const aHandle: THandle): TBitmap;
[b]var
  /bDC, hdcMem: HDC;
  aRect: TRect;
  hBMP: HBitmap;
  aWidth, aHeight: Integer;
[b]begin
  /bResult : =  TBitmap.Create;
  dc := GetWindowDC(aHandle);
   if  (dc > 0) [b]then
  try
    /bhdcMem : = CreateCompatibleDC(dc);
    if (hdcMem > 0) [b]then
    try
      /bGetWindowRect(aHandle, aRect);
      aWidth :=  aRect.Right - aRect.Left;
      aHeight := aRect.Bottom - aRect.Top;
      hBMP := CreateCompatibleBitmap(dc, aWidth, aHeight);
       if  (hBMP > 0) [b]then
      try
        /bSelectObject(hdcMem, hBMP);
        PrintWindow(aHandle, hdcMem, 0);
        with Result [b]do
        try
          /bWidth : = aWidth;
          Height :=  aHeight;
          BitBlt(Canvas.Handle, 0, 0, aWidth, aHeight, hdcMem, 0, 0, srcCopy);
        [b]except
          begin
            /bFreeAndNil(Result);
             raise   Exception.Create('La capture a échouée');
          end;
        end;
      [b]finally
        /bDeleteObject(hBMP);
      end;
    [b]finally
      /bDeleteObject(hdcMem);
    end;
  [b]finally
    /bReleaseDC(aHandle, dc);
  end;
end;

procedure TForm10.Button1Click(Sender: TObject);
[b]begin
  /bTimer1.Enabled : = True;
end;

procedure TForm10.Timer1Timer(Sender: TObject);
[b]var
  /baBMP: TBitmap;
[b]begin
  /bTimer1.Enabled := False;
  aBMP := DoShot(GetForegroundWindow);
  if Assigned(aBMP) [b]then
  begin
    /bImage1.Picture.Assign(aBMP);
    FreeAndNil(aBMP);
  end;
end;

end.[hr]

pour l'utilisation:

il faut:
mettre une fiche partiellement en dehors de l'écran
démarrer l'application
Cliquer sur le bouton1
et recliquer sur la fiche qui doit être copiée (pour lui donner le focus)

je sais c'est pas très pratique mais c'est que pour la démo



[hr]@+Cirec
[hr]
1
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
9 août 2011 à 12:13
Bonjour,

Message déplacé de javascript vers delphi.

Cordialement
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
9 août 2011 à 14:18
Christian
Merci coucou747, désolé pour l'erreur
bonne journée
Christian
0
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
9 août 2011 à 14:33
Aucun problème, je retire le réponse acceptée et espère que des gens pourront t'aider sur ce sujet.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
9 août 2011 à 15:23
Salut,

Et en passant par GetFormImage ?

_______________________________________
Soutenez Wikimédia France aujourd'hui : http://dons.wikimedia.fr
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
9 août 2011 à 17:32
Merci à Caribensila et particulièrement à cirec pour vos réponse, je vais essayer de tout recopier sans me tromper et vous dirais si cela fonctionne.
Ou est le bon temps du basic avec simplement "Print", même en Turbo pascal, enfin il faut vivre avec le progrès...

Christian
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
9 août 2011 à 18:06
Bien, j'ai charger le code comme définit.
Après le lancement du programme, j'ai "Form1" qui apparait sans image (deux essais avec extension .JPG et .BMP), j'ai cliqué sur Bouton1, et une seconde "Form1" s'est affiché, et a chaque fois que je clique une nouvelle forme apparait mais rien ne s'imprime ?

Christian
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
9 août 2011 à 18:45
Cirec, je me suis permis de modifier ton programme comme ci-dessous :

begin
Timer1.Enabled := False;
aBMP := DoShot(GetForegroundWindow);
if Assigned(aBMP) then
begin
{Image1.Picture.Assign(aBMP); }

PrintDialog1.Execute;
{FreeAndNil(aBMP); }
Form1.Print;
end;

J'ai ajouté l'appel de la boîte de dialogue imprimante et la demande d'impression, supprimé deux lignes de ton programme et apparemment ça marche maintenant.
Il me reste a insérer ces lignes dans mon programme !
A suivre !



Christian
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
14 août 2011 à 15:29
Bon, hélas, ça ne fonctionne pas, mes modifications ne sont pas valable, c'était n'importe quoi, excuse moi Cirec!
Christian
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
14 août 2011 à 16:43
Re,

Ca m'étonnerait que le code de Cirec plante.
Mais je ne l'ai pas essayé car, chez moi, ça fonctionne avec ce simple code sous D7 et XP (à adapter à tes besoins) :

uses printers;

procedure TForm1.Button1Click(Sender: TObject);
  var FormImage : Tbitmap;
begin
  FormImage := GetFormImage;
  try
    Printer.BeginDoc;
    Printer.Canvas.StretchDraw(Rect(0,0,Printer.PageWidth,Printer.PageHeight),FormImage);
    Printer.EndDoc
  finally FreeAndNil(FormImage); end;
end;

_______________________________________
Soutenez Wikimédia France aujourd'hui : http://dons.wikimedia.fr
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
14 août 2011 à 18:01
Bonjour Caribensila, merci de ta réponse.
J'ai entré ton code dans ma procédure d'impression, saisi l'utilisation :
uses printers;

Et la variable :
var FormImage : Tbitmap;

en début de programme, puis lancé celui-ci
Le compilateur m'a surligné Uses Printers;
et m'envoie un message d'erreure :
Déclaration attendu(e) mais identificateur 'pinters' trouvé(e)
Là je sèche ?

Christian
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
14 août 2011 à 18:03
Je précise que je suis débutant et "simple code sous D7 et XP " ne me dit pas grand chose, je suis pas sous XP mais sous Windows 7, je ne sais si cela a une importance ?


Christian
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
14 août 2011 à 18:19
Mets "printers" dans les uses de ton projet comme ceci :

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, printers;
_______________________________________
Soutenez Wikimédia France aujourd'hui : http://dons.wikimedia.fr
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
14 août 2011 à 18:25
autant pour moi, j'avais confondu un point virgule avec une virgule, par contre j'ai un message d'insulte :
Le projet Ticket.exe a provoqué une classe d'exception EAccessViolation avec message 'Violation d'acces à l'adresse 00403104 dans le module 'Ticket.exe'.
Lecture de l'adresse 0575C080'.Processus stoppé. Utilisez Pas-à-Pas ou Exécuter pour continuer.
???

Christian
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
14 août 2011 à 18:35
Crée un nouveau projet pour tester ce code qui fonctionne chez moi :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}

uses printers;

procedure TForm1.Button1Click(Sender: TObject);
var FormImage : Tbitmap;
begin
FormImage := GetFormImage;
  try
  	Printer.BeginDoc;
  	Printer.Canvas.StretchDraw(Rect(0,0,Printer.PageWidth,Printer.PageHeight),FormImage);
  	Printer.EndDoc
  finally FreeAndNil(FormImage); end;
end;

end.


Si ça ne fonctionne pas sous Seven, je ne peux pas t'aider davantage. Désolé.

_______________________________________
Soutenez Wikimédia France aujourd'hui : http://dons.wikimedia.fr
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
15 août 2011 à 09:22
Bien, merci pour ta patience, je vais faire selon tes information, je te tiendrais informé des résultats.
A bientôt Caribensila

Christian
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
15 août 2011 à 10:55
Salut Caribensila,

effectivement j'ai testé le code avant de le poster
Mais je suis pas certain que ton code fonctionne réellement (relis la question de CharlyLima) quand la fenêtre à capturer est en partie en dehors de l'écran !!!

Sinon CharlyLima, en modifiant le code que je t'ai donné ... ben il ne fait plus rien

Je sais que l'exemple n'est pas terrible et qu'il faut bien lire mes explications pour pouvoir utiliser l'exemple mais il fonctionne, juste qu'à la place d'imprimer il affiche l'image dans un TImage.


Bon on va essayer un mix des deux codes :

tu recopies, depuis mon exemple, la déclaration de fonction "PrintWindow" et la fonction DoShot puis tu y ajoutes le code de Caribensila que tu modifies légèrement comme suit :

function PrintWindow(ahwnd: HWND; hdcBlt: HDC; nFlags: UINT): Bool; stdcall;
external 'User32.dll' name 'PrintWindow';

implementation

{$R *.dfm}
uses printers;
// ATTENTION cette fonction crée un TBitmap c'est à vous de le libérer à la fin
function DoShot(const aHandle: THandle): TBitmap;
var
  DC, hdcMem: HDC;
  aRect: TRect;
  hBMP: HBitmap;
  aWidth, aHeight: Integer;
begin
  Result := TBitmap.Create;
  dc := GetWindowDC(aHandle);
  if (dc > 0) then
  try
    hdcMem := CreateCompatibleDC(dc);
    if (hdcMem > 0) then
    try
      GetWindowRect(aHandle, aRect);
      aWidth := aRect.Right - aRect.Left;
      aHeight := aRect.Bottom - aRect.Top;
      hBMP := CreateCompatibleBitmap(dc, aWidth, aHeight);
      if (hBMP > 0) then
      try
        SelectObject(hdcMem, hBMP);
        PrintWindow(aHandle, hdcMem, 0);
        with Result do
        try
          Width := aWidth;
          Height := aHeight;
          BitBlt(Canvas.Handle, 0, 0, aWidth, aHeight, hdcMem, 0, 0, srcCopy);
        except
          begin
            FreeAndNil(Result);
            raise  Exception.Create('La capture a échouée');
          end;
        end;
      finally
        DeleteObject(hBMP);
      end;
    finally
      DeleteObject(hdcMem);
    end;
  finally
    ReleaseDC(aHandle, dc);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
  var FormImage : Tbitmap;
begin
  FormImage := DoShot; // <-- ceci a changé
  try
    Printer.BeginDoc;
    Printer.Canvas.StretchDraw(Rect(0,0,Printer.PageWidth,Printer.PageHeight), FormImage);
    Printer.EndDoc
  finally 
    FreeAndNil(FormImage); 
  end;
end;









[hr]@+Cirec
[hr]
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
15 août 2011 à 15:23
Merci
Cirec pour ta précision,
J'ai refait un nouveau projet pour essayer vos propositions, et j'obtiens un message d'erreur suivant :
pas[78]:Pas assez de paramètres originaux
pas[78]:';'attendu(e) mais '.' trouvé(e)
pas[78]:Déclaration attendu(e) mais fin de fichier trouvé(e)

et la ligne contenant :
FormImage := DoShot; // <-- ceci a changé
est surlignée ??


Christian
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
15 août 2011 à 15:24
Salut Cirec,

« Mais je suis pas certain que ton code fonctionne réellement (relis la question de CharlyLima) quand la fenêtre à capturer est en partie en dehors de l'écran !!! »


Si, si. Mon code fonctionne pour toute la fenêtre, même en dehors de l'écran.

Mais je m'aperçois que mon code n'est quand même pas d'équerre.
En effet, GetFormImage ne capture pas le texte d'un ComboBox, par exemple.
On pourrait le corriger ainsi (pour les ComboBox) :

uses clipbrd, printers;

procedure TForm1.Button1Click(Sender: TObject);
var BMP : Tbitmap;
begin
keybd_event(VK_SNAPSHOT,1,0,0); //Capture d'ecran de la fenêtre active.
if Clipboard.HasFormat(cf_BitMap) then begin
  	BMP := Tbitmap.Create;
   	try
   		BMP.LoadFromClipboardFormat(cf_BitMap,ClipBoard.GetAsHandle(cf_Bitmap),0);
  		Printer.BeginDoc;
                Printer.Canvas.StretchDraw(Rect(0,0,self.Width*5,self.Height*5),BMP);
  		Printer.EndDoc;
  	finally FreeAndNil(BMP); end;
  end else exit;
end;


Mais, à ce moment-là, on perd ce qui est hors de l'écran.


Bref, et pour conclure, c'est le code de Cirec le plus polyvalent ! (ce qui n'étonnera personne ici-bas).


PS: Mais cependant corriger le code de Cirec comme ceci
procedure TForm1.Button1Click(Sender: TObject);
var FormImage : Tbitmap;
begin
FormImage := DoShot(GetForegroundWindow); // <-- ceci a changé
...



_______________________________________
Soutenez Wikimédia France aujourd'hui : http://dons.wikimedia.fr
0
cs_CharlyLima Messages postés 27 Date d'inscription jeudi 24 août 2006 Statut Membre Dernière intervention 26 décembre 2015
15 août 2011 à 16:03
Merci Caribensila et Cirec pour votre persévérance, l'ensemble de vos deux propositions semble fonctionner sur mon petit projet d'essai, reste a l'installer sur mon projet définitif, mais là si il ne fonctionne pas ce sera de ma faute.
Sinon, vous connaissez un bon livre traitant de Delphi 7 qui contiendrait toutes les fonctions et procédures a la portée de ma faible connaissance, j'ai actuellement "Le programmeur de CampusPress" mais il n'est pas très complet et peux explicite pour retrouver quelque chose.*
%Merci a vous deux



Christian
0
Rejoignez-nous