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
A voir également:
Je voudrais changer ma methode d'impression, que me conseillez vous ?
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.
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
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)
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
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.
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.
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.
'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)
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)?
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.
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
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.