Je voudrais changer ma methode d'impression, que me conseillez vous ?

Signaler
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013
-
 Utilisateur anonyme -
Bonjour,
J'ai une appli qui effectue des calculs que je peux jusqu'à présent imprimer via un button print de cette maniere :
- j'ai crée un form que j'ai appelé formprint
- ma class impression est la suivante :
Imports System.Drawing.Printing
 Public Class ClassImpression
 Private Declare Function StretchBlt Lib "gdi32.dll" Alias "BitBlt" (ByVal _
           hdcDest As IntPtr, ByVal nXDest As Integer, ByVal nYDest As _
           Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal _
           hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, _
           ByVal dwRop As System.Int32) As Long
    Private myimage As Bitmap
    Private thectrl As Control
    Private Function Capturectrl(ByVal ctrl As Control) As Bitmap
        Dim memoryImage As Bitmap
        Dim mygraphics As Graphics = ctrl.CreateGraphics()
        Dim s As Size = ctrl.Size
        memoryImage = New Bitmap(s.Width - 10, s.Height - (SystemInformation.FrameBorderSize.Width + 6 + SystemInformation.CaptionHeight), mygraphics)
        Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage)
        Dim dc1 As IntPtr = mygraphics.GetHdc
        Dim dc2 As IntPtr = memoryGraphics.GetHdc
        StretchBlt(dc2, 0, 0, ctrl.ClientRectangle.Width, _
           ctrl.ClientRectangle.Height, dc1, 0, 0, 13369376)
        mygraphics.ReleaseHdc(dc1)
        memoryGraphics.ReleaseHdc(dc2)
        Return memoryImage
    End Function
    Public Function GetPreview() As Bitmap
        Return Capturectrl(thectrl)
    End Function
    Public Sub printdoc()
        Try
            Dim prtd As New PrintDialog
            'document à imprimer
            Dim doc As New PrintDocument
            myimage = Capturectrl(thectrl)
            AddHandler doc.PrintPage, AddressOf printform
            'paramètres de page
            Dim ps As New PageSettings
            ps.Landscape = False
            doc.DefaultPageSettings = ps
            'indique à la prévisualisation le document à montrer
            prtd.Document = doc
            If prtd.ShowDialog = DialogResult.OK Then
                prtd.Document.Print()
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub
    Private Sub printform(ByVal sender As Object, ByVal e As PrintPageEventArgs)
        Try
            e.Graphics.DrawImage(myimage, 0, 0)
            e.HasMorePages = False
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub
    Public Sub New(ByVal ctrl As Control)
        thectrl = ctrl
    End Sub
End Class

- mon bouton print renvoie le code suivant :
 Private Sub print_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles print.Click
               If printerlist() = String.Empty Then
            messageaff = "No printer available on this station"
            infoaff = "Error"
            MessageBox.Show(messageaff, infoaff, MessageBoxButtons.OK, MessageBoxIcon.Error)
        Else
        Try
            Dim p As New ClassImpression(Me)
            showimage = p.GetPreview
            p.printdoc()

        Catch ex As Exception
                messageaff = "Printer Error : end of the impression"
                infoaff = "Error"
                MessageBox.Show(messageaff, infoaff, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

        End If
           End Sub


J'ai par contre de gros problèmes avec cette méthode :
- Je voudrais pouvoir imprimer 2 feuilles format A4 ce qui n'est pas le cas actuellement.
- Je suis limité à la résolution de mon écran pour l'impression. Pour exemple :

Impression faite avec un moniteur ayant une résolution verticale de 1024



La même mais avec un ecran ayant une résolution verticale de 768 (moniteur 16/10)



Je pense qu'il faut donc que je change ma méthode d'impression. Peut être générer un pdf par exemple, que je puisse imprimer au moins 2 feuilles car j'ai de nouvelles données a imprimer et surtout m'affranchir de la résolution des ecrans car cela devient insupportable.

Pourrais je avoir un conseil avisé ?
Merci beaucoup

19 réponses


Bonsoir,

StretchBlt
Que fait donc cette api dans ton code ?
L'objet Graphics que tu as nommé 'memoryGraphics' dans ton code, possède une méthode CopyFromScreen qui te permet de t'affranchir de l'api.

Il existe aussi dans le framework, l'objet Screen qui te permet de connaître la résolution de la machine de l'utilisateur.

Avec une simple règle de trois et la méthode DrawImage de ton 'memoryGraphics' (DrawImage possède une surcharge intéressante pour le redimensionnement), tu devrais t'en tirer facilement en 2 ou 3 lignes de codes maxi.
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

Bonjour banana32
ben je voulais faire un redimensionnement d'image et vu que la propriete stretch n'existe pas pour les control pictures, je m'etais dit que ca allait le faire ... lourde erreur ....

Apres, je pensais mettre le
e.HasMorePages = False
à true pour pouvoir avoir plusieurs pages mais ca ne resoud pas mon probleme car jusqu'à maintenant, je fais une sorte de capture qui s'enregistre en .jpg in fine. Or comment faire pour n'avoir qu'un fichier jpg de plusieurs pages ????? en PDF c'est concevable mais pas en jpg non ?
d'ou mon idée de passer par un pdf mais franchement, je ne sais pas faire du tout.

En attendant, je vais regarder ce que tu me propose afin, deja, de m'affranchir des soucis de dimensionnement
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

en fait voila ce que je voudrais avoir au final; Un fichier pdf qui contiendrait ceci :




ce que je ne peux pas faire en jpg

ce que je ne peux pas faire en jpg

Bien sûr que c'est possible avec la méthode Save d'un objet Bitmap (memoryImage dans ton code).

As-tu potassé tous les liens que j'ai pris la peine de t'indiquer dans mon précedent post ?

Voici un petit exemple d'un formulaire de taille 300x300 sauvegardé en jpg en taille réelle et réduite :
        'bitmap 100x100
        Dim b As New Bitmap(300, 300)
        'outil graphique
        Dim g As Graphics = Graphics.FromImage(b)
        'fond bleu
        g.CopyFromScreen(New Point(Me.Left, Me.Top), New Point(0, 0), New Size(300, 300), CopyPixelOperation.SourceCopy)
        'carré rouge au centre
        g.DrawRectangle(New Pen(Brushes.Red, 3), 100, 100, 100, 100)
        'écriture quelconque
        g.DrawString("blabla", New Font("Courier New", 30), Brushes.Blue, 25, 25)
        'sauvegarde jpeg
        b.Save("taille_reelle.jpg", Imaging.ImageFormat.Jpeg)
        'bitmap 50x50
        Dim bmini As New Bitmap(100, 100)
        'outil graphique
        g = Graphics.FromImage(bmini)
        'réduction en jpeg
        g.DrawImage(b, New Rectangle(0, 0, 100, 100), New Rectangle(0, 0, 300, 300), GraphicsUnit.Pixel)
        'sauvegarde
        bmini.Save("taille_mini.jpg", Imaging.ImageFormat.Jpeg)
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

J'ai bien pris le temps de consulter les liens msdn que tu m'as donné oui.
N'en demeure pas moins que je ne vois toujours pas et je n'ai jamais vu de ma vie un jpg contenant 2 pages (pas une grande page redimensionnée mais bel et bien 2 pages). Et je vois encore moins comment materialiser ces 2 pages sur un form puisque je suis limité a 1044 dans la conception.

Il y a vraiment quelque chose qui m'echappe serieusement la

merci de ton aide

Il y a vraiment quelque chose qui m'echappe serieusement la

Il ne faut pas oublier que je ne suis pas à ta place et que je ne connais de ton problème que ce que tu en as décrit.

Ce que j'ai cru comprendre, c'est que tu veux imprimer sur papier A4, un graphique affiché sur un contrôle et que tu veux l'imprimer sur 2 feuilles puisqu'il est plus grand qu'une seule feuille A4.

De plus, tu dis vouloir imprimer ce graphique en fonction de la taille de l'écran de l'utilisateur.

En te servant d'une règle de trois pour respecter le rapport : taille d'écran <-> format A4, il te suffirait de réduire (ou d'agrandir cette image pour qu'elle se 'répande' sur une ou 2 pages papier.

Je t'ai donc proposé un exemple qui montre comment réduire l'image affichée sur ton contrôle de manière à ce qu'elle contienne sur une seule feuille A4. Bien sur, tu peux aussi agrandir cette image.

Si vraiment ce n'est pas possible, tu peux, grâce à la méthode DrawImage, découper l'image en deux zones puis les imprimer ensuite.

Cette ligne de code :
g.DrawImage(b, New Rectangle(0, 0, 100, 100), New Rectangle(0, 0, 300, 300), GraphicsUnit.Pixel)

... le 2eme rectangle passé en paramètre à cette méthode permet de ne garder qu'une partie de l'image source. Le premier rectangle devra reproduire les dimensions de ta feuille A4, puisqu'il s'agit du rectangle destination que tu veux imprimer.

Voilà ce que j'ai compris de ton problème.
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

Re banana32,
Je me suis surement mal exprimé et je m'en excuse par avance. C'est vrai qu'il y a enormement de difference entre voir "de visu" un probleme et l'énoncer correctement.
A l'origine, nous avions tous a la boite des moniteurs 4:3 en 1280X1024
Le logiciel a été développé il y a maintenant pas mal de temps et son but est d'effectuer des calculs a partir de données entrées pour donner un resultat sous forme formulaire qui a pour size 763;1044 (limité automatiquement a la resolution verticale de l'ecran + 20).
Voici le formulaire d'impression dans son etat initial :



le bouton close ne nous interesse pas au cas présent.
Le bouton validate capture l'image exacte du formulaire et l'enregistre en jpg dans un repertoire du NAS du boulot.
Le bouton print declenche l'impression voici la sub
Private Sub print_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles print.Click
               If printerlist() = String.Empty Then
            messageaff = "No printer available on this station"
            infoaff = "Error"
            MessageBox.Show(messageaff, infoaff, MessageBoxButtons.OK, MessageBoxIcon.Error)
        Else
        Try
            Dim p As New ClassImpression(Me)
            showimage = p.GetPreview
            p.printdoc()

        Catch ex As Exception
                messageaff = "Printer Error : end of the impression"
                infoaff = "Error"
                MessageBox.Show(messageaff, infoaff, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

        End If
           End Sub 


jusqu'ici, tout allait bien et je ne me souciais pas de l'impression qui fonctionnait MAIS :
- Nous avons changé nos moniteurs pour des LED 16/9 qui ne peuvent
afficher 1024 en resolution verticale. Du coup, impossible d'imprimer
en entier mon formulaire
- Les données a imprimer sont maintenant plus nombreuses et impossible de
les faire tenir sur un seul formulaire 763;1044

Je voulais donc trouver une solution pour pouvoir
- afficher ces 2 pages
- Imprimer ces 2 pages (bouton print)
- enregistrer ces 2 pages en un seul fichier (bouton validate)

J'ai regardé tes liens, tout le chapitre impression du "lasserre" et recherche pas mal sur le web mais je n'y arrive absolument pas, je n'ai pas même idée de comment procéder.

Voili voila, en esperant avoir pu eclairer de manière plus "lisible" sur mon souci

N'oublie pas que l'objet Screen (vu plus haut), te fournis les tailles de la machine qui héberge l'application.
Il existe la librairie iTextSharp (sous forme de framework installable) pour créer des pdf facilement sous vb .NET.
En t'inspirant de tout ce que tu as appris (je l'espère) dans ce fil de discussion, tu devrais pouvoir avancer maintenant.

Edit :
te fournis les tailles de l'écran de la machine
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

Bonsoir banana32
j' ai teste durant 2 jours ce que tu m'avais appris, notamment l'utilisation de la librairie iTextSharp mais aussi j'ai bidouillé un truc pour essayer d'utiliser pdf creator.

Une chose est pourtant absolument pas claire pour moi.
Mon formulaire d'impression (printform) est limité en hauteur à 1044. Ca c'est un fait. Comment pourrais je visualiser dans ce cas a l'ecran un document qui necessite une resolution maximale plus grande.

C'est peut être bete ou surement du a un manque d'habitude, mais cela est totalement flou dans ma tête.

Si par exemple on prends un document fait avec word, dans word on peut voir plusieurs pages en scrollant. Mais dans mon cas je ne comprends absolument pas le concept

Le contrôle 'Panel' disponible dans ta barre d'outils devrait résoudre ton problème. Il faut définir sa propriété AutoScroll à True. Un PictureBox contenant ton image (plus grande que le panel) et placé sur ce panel provoquera l'affichage des scrollbars qui te permettront de faire défiler ton image en entier.

Un petit exemple pour illuster :
'ajout d'un panel au formulaire
Dim pnl As New Panel With {.Parent Me, .Bounds New Rectangle(20, 20, 200, 200), .AutoScroll = True}
'nouveau bitmap de taille de l'écran
Dim b As New Bitmap(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
'outil de dessin
Dim g As Graphics = Graphics.FromImage(b)
'copie de l'écran sur le bitmap
g.CopyFromScreen(New Point(0, 0), New Point(0, 0), Screen.PrimaryScreen.WorkingArea.Size, CopyPixelOperation.SourceCopy)
'ajout d'un picturebox sur le panel
Dim p As New PictureBox With {.SizeMode PictureBoxSizeMode.AutoSize, .Parent pnl}
'affichage de l'image
p.Image = CType(b.Clone, Image)
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

Bonjour banana32
Tout dabord merci de ton aide
effectivement, cela resoud une partie de mon souci, dans la mesure ou je peux voir avec le scroll toute la hauteur de mon form, mais par contre cela ne resoud pas le souci d'impression. C'est comme si quelque chose ne collait pas dans le :
Private Function Capturectrl(ByVal ctrl As Control) As Bitmap
        Dim memoryImage As Bitmap
        Dim mygraphics As Graphics = ctrl.CreateGraphics()
        Dim s As Size = ctrl.Size
        memoryImage = New Bitmap(s.Width - 3, s.Height - (SystemInformation.FrameBorderSize.Width + 3 + SystemInformation.CaptionHeight), mygraphics)
        Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage)
        Dim dc1 As IntPtr = mygraphics.GetHdc
        Dim dc2 As IntPtr = memoryGraphics.GetHdc
        StretchBlt(dc2, 0, 0, ctrl.ClientRectangle.Width, _
           ctrl.ClientRectangle.Height, dc1, 0, 0, 13369376)
        mygraphics.ReleaseHdc(dc1)
        memoryGraphics.ReleaseHdc(dc2)
        Return memoryImage
    End Function
de mon classimpression

Je me demandais,, crystal report ne pourrait pas faciliter la tache ? suis je obligé de le relier a une DB (j'ai une db access mais qui ne contient pas tous les elements que j'imprime)?

C'est comme si quelque chose ne collait pas
Je constate que tu utilises encore l'api.

En outre, je t'ai montré plus haut la manière dont on réduit (ou agrandit) la taille d'une image afin de pouvoir l'imprimer.

Je me demandais,, crystal report ne pourrait pas faciliter la tache ?
Ouvre un autre sujet de discussion pour poser cette question.

A+
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

si tu fais reference a StretchBlt, elle est juste présente dans ce post car j'ai fait un copier coller de mon premier post, mais j'utilise bien CopyFromScreen

Je m'embrouille un peu les meninges en essayant de faire plusieurs choses a la foi.
Je reviens sur mon redimensionnement d'image et je verrai après pour itextxcharp et ses pdf

Pour crystal, c'etait juste une idée en passant, je ne pense pas l'exploiter. Je n'ai pas voulu créer un topic inutile.

Merci beaucoup
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

me revoila, alors effectivement j'arrive a redimensionner pour pouvoir imprimer, mais problème de taille : j'ai tellement de choses a imprimer que de fait, le redimensionnement est important et tout devient illisible car trop petit
je ne sais plus quoi faire

Bonsoir,

Au lieu de réduire, tu peux couper l'image en plusieurs zones et les agrandir de façon à remplir chaque page à imprimer.
Messages postés
409
Date d'inscription
jeudi 30 juin 2005
Statut
Membre
Dernière intervention
21 novembre 2013

c'est exactement ce que je voudrais faire, mais je ne comprends pas comment faire pour être honnète.
Ce que j'ai du mal a comprendre, c'est le lien entre, par exemple, un rapport qui serait imprimé en plusieurs pages, et la visualisation de celui ci qui est limitée a la resolution max + 20 de mon ecran (hormis a tout mettre dans un panel)

Une fois que tu as fait ta copie d'écran sur un Bitmap comme montré plus haut, la seule surcharge de la méthode DrawImage de l'objet Graphics qui peut te servir sera celle-ci. Elle devra être utilisée autant de fois que nécessaire avec des zones différentes bien entendu. Le rectangle source devant définir des zones de ton bitmap de base et le rectangle destination représentant la taille d'une feuille A4 par exemple.
Tu te retrouveras alors avec plusieurs 'Bitmap' de la taille d'une feuille A4 représentant tes zones agrandies et que tu n'auras plus qu'à imprimer.