locked
Printing EMF format via PrintDocuments.PrintPage RRS feed

  • Question

  • how can print an image that i emf as memorystream. Every time try to print i get an error saying Para in not valid or generic gdi+ error. I can save the image as file just fine, but i dont want to do that. I have tried with other formats and they work, but i need to have wmf or emf format because of the resolution. 

    here is the code.

    thank you,

    Shane

    Private Sub PrintPreview_PrintPage(sender As Object, ev As PrintPageEventArgs) 'Note, the chart printing code wants to print in pixels. Dim marginBounds As Rectangle = ev.MarginBounds Dim chart2 As New Chart 'Creates the second chart to changes anything Using ms As New System.IO.MemoryStream 'Saves the current chart Chart1.Serializer.Save(ms) 'Loads the current chart into second chart chart2.Serializer.Load(ms) If Not (ev.Graphics.PageUnit = GraphicsUnit.Pixel) Then ev.Graphics.PageUnit = GraphicsUnit.Pixel 'sets the size of the object marginBounds.X = CInt(marginBounds.X * (ev.Graphics.DpiX / 100.0F)) marginBounds.Y = CInt(marginBounds.Y * (ev.Graphics.DpiY / 100.0F)) marginBounds.Height = CInt(marginBounds.Height * (ev.Graphics.DpiX / 100.0F)) marginBounds.Width = CInt(marginBounds.Width * (ev.Graphics.DpiY / 100.0F)) End If Using ms2 As New System.IO.MemoryStream
    Dim g As Graphics = CreateGraphics()
    'Save the image memorystream chart2.SaveImage(ms2, System.Drawing.Imaging.ImageFormat.Emf) ' chart2.SaveImage("image.emf", System.Drawing.Imaging.ImageFormat.Emf) ''gets the images from memory stream. Dim mf As Metafile = New Metafile(ms2, g.GetHdc) 'draws the image as for document ev.Graphics.DrawImage(mf, marginBounds) End Using End Using End Sub


    Thursday, May 7, 2015 4:11 PM

Answers

  • I dont really know but apparently there is no encoder for metafile in .net. Here are a couple threads with apparent work arounds.

    You know that metafiles are more of a scalable vector file thus the infinate resolution when redrawn. It could be that what you have from serializing the chart is a bitmap.

    Is this the line where you get the error?

       Dim mf As Metafile = New Metafile(ms2, g.GetHdc)

    Is that assigning a bitmap to a metafile?

    These two links have a couple work arounds that you may be able to puzzle out. Looks tuff.

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/2c119c1e-d735-4824-81ab-1292af319d6e/metafile-serialization-impossible-?forum=csharpgeneral


    https://social.msdn.microsoft.com/Forums/vstudio/en-US/12a1c749-b320-4ce9-aff7-9de0d7fd30ea/how-to-save-or-serialize-a-metafile-solution-found?forum=csharpgeneral


    Another way to have better printer resolution is to start with a bigger bitmap. The printer resolution islike 600 dpi. The default monitor screen is 96 dpi. So if your chart image is in screen res and you print to printer res it is being enlarged x 6.

    Therefore you should start with an image that is x6 bigger. I am not sure how. Maybe you can make a chart control that is x6 bigger and capture the image? Well, maybe not.

    But the way metafiles work, you capture the gdi drawing to the metafile. Are you familar with it? Then when you draw the image it repeats the gdi drawing steps to make the screen image which is now a bitmap of pixels. Not the same. If you have an original metafile you can print it like you are doing and you get the vector resolution. Somehow you would have to capture the chart as a true metafile. Sounds like serializing is something else, like a bitmap.

    Hope it helps.

    Friday, May 8, 2015 3:10 AM
  • Hello Tommy,

       What i did is save the file as emf format and the open as image then passed the image to the Graphic.DrawImage and it worked fine.. I dont like the idea of making an image first then loading the image, but it works for now.. When I can find another way to do it, I will..

    Thank you,

    Shane

    Friday, May 8, 2015 11:00 AM

All replies

  • I dont really know but apparently there is no encoder for metafile in .net. Here are a couple threads with apparent work arounds.

    You know that metafiles are more of a scalable vector file thus the infinate resolution when redrawn. It could be that what you have from serializing the chart is a bitmap.

    Is this the line where you get the error?

       Dim mf As Metafile = New Metafile(ms2, g.GetHdc)

    Is that assigning a bitmap to a metafile?

    These two links have a couple work arounds that you may be able to puzzle out. Looks tuff.

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/2c119c1e-d735-4824-81ab-1292af319d6e/metafile-serialization-impossible-?forum=csharpgeneral


    https://social.msdn.microsoft.com/Forums/vstudio/en-US/12a1c749-b320-4ce9-aff7-9de0d7fd30ea/how-to-save-or-serialize-a-metafile-solution-found?forum=csharpgeneral


    Another way to have better printer resolution is to start with a bigger bitmap. The printer resolution islike 600 dpi. The default monitor screen is 96 dpi. So if your chart image is in screen res and you print to printer res it is being enlarged x 6.

    Therefore you should start with an image that is x6 bigger. I am not sure how. Maybe you can make a chart control that is x6 bigger and capture the image? Well, maybe not.

    But the way metafiles work, you capture the gdi drawing to the metafile. Are you familar with it? Then when you draw the image it repeats the gdi drawing steps to make the screen image which is now a bitmap of pixels. Not the same. If you have an original metafile you can print it like you are doing and you get the vector resolution. Somehow you would have to capture the chart as a true metafile. Sounds like serializing is something else, like a bitmap.

    Hope it helps.

    Friday, May 8, 2015 3:10 AM
  • Hello Tommy,

        I will look at post you gave me.. I am getting the error on this line  ev.Graphics.DrawImage(mf, marginBounds) because it can not encode the metafile. I have tried with different saving and its the same results. I have the emf as memorystream and its not encoding it correctly, and i want to have vector image, I have tried png and jpg and they are all just not good enough resolution. I might try a very dpi on bmp..

    Shane

    Friday, May 8, 2015 3:22 AM
  • Hello Tommy,

       What i did is save the file as emf format and the open as image then passed the image to the Graphic.DrawImage and it worked fine.. I dont like the idea of making an image first then loading the image, but it works for now.. When I can find another way to do it, I will..

    Thank you,

    Shane

    Friday, May 8, 2015 11:00 AM
  • Hello Tommy,

       What i did is save the file as emf format and the open as image then passed the image to the Graphic.DrawImage and it worked fine.. I dont like the idea of making an image first then loading the image, but it works for now.. When I can find another way to do it, I will..

    Thank you,

    Shane


    If you can save the file as an emf it seems you should be able to print it? Seems there is just something in the code that is not quite right that can be worked out if we knew what it was?

    You should be able to draw what you have in your stream onto a large bitmap in memory. Then print that as an image. Key being by drawing the emf, if that is what it is, on a memory bitmap that is the size of the printer page in pixels, you will get the resolution from the emf drawn on the large bitmap and then you can print that 1:1.

    ie Read metafile into metafile graphic, Draw on a bitmap at printergraphic.dpi x pringer.pagesize in pixels. Then drawimage with that large memory bitmap to the printer. You should get the same resolution you would get if you printed the original metafile. Its the same thing. You are just drawing it in memory first instead of direct to the printer (which is a bitmap).

    Anyway, glad you made progress with it.

    Friday, May 8, 2015 12:32 PM
  • PS

    This prints the metafile direct to the printer.

    'read and print metafile example
    Public Class Form8
        Private WithEvents PrintDocument1 As PrintDocument = New PrintDocument
        Private PrintPreviewDialog1 As New PrintPreviewDialog
        Private PrintingActive As Boolean
        Private theMetafile As Metafile
    
        Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
            'for print preview the picturebox graphics coord 0,0 is at upper left of the white page graphic
            'but for the printer 0,0 is at the non printable offset from the edge of the paper
            'so we need to translate 0, 0 to draw to the printer but not the preview picturebox
            'the first call here is for the preview graphic, then all calls after are to print
            If PrintingActive Then
                'values of the printable rectangle coordinates
                Dim paRectF As RectangleF
                paRectF = PrintDocument1.DefaultPageSettings.PrintableArea()
                e.Graphics.TranslateTransform(-paRectF.X, -paRectF.Y)
            End If
    
            With e.Graphics
                Dim scalefactor As Single
                Dim l, t, w, h As Integer
                Dim ratio As Single = CSng(theMetafile.Width / theMetafile.Height)
    
                'size to fit window maintaining aspect
                If ratio > .VisibleClipBounds.Width / .VisibleClipBounds.Height Then
                    w = CInt(.VisibleClipBounds.Width)
                    h = CInt(w / ratio)
                    t = CInt((.VisibleClipBounds.Height / 2) - (h / 2))
                Else
                    h = CInt(.VisibleClipBounds.Height)
                    w = CInt(h * ratio)
                    l = CInt((.VisibleClipBounds.Width / 2) - (w / 2))
                End If
    
                'draw the image on the graphics
                .DrawImage(theMetafile, l, t, w, h)
            End With
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Try
                theMetafile = New Metafile("c:\bitmaps\tipple1.wmf")
    
                'show print preview with printdoc
                'prints if user clicks button on print preview
                PrintingActive = False              'set this false so preview coordinates are used for preview
                PrintPreviewDialog1.Document = PrintDocument1
                PrintPreviewDialog1.ShowDialog()
            Catch ex As Exception
                MsgBox("Problem Printing:" & Chr(13) & ex.Message, MsgBoxStyle.Exclamation)
            End Try
        End Sub
    
    End Class
    
    

    This draws the metafile on a memory bitmap the size of the print page in pixels and then prints that. Result is the same.

    Option Strict On
    
    Imports System.Drawing.Printing
    Imports System.Drawing.Imaging
    Public Class Form6
        'read and print metafile example
        Private WithEvents PrintDocument1 As PrintDocument = New PrintDocument
        Private PrintPreviewDialog1 As New PrintPreviewDialog
        Private PrintingActive As Boolean
        Private theMetafile As Metafile
    
    
        Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
            'for print preview the picturebox graphics coord 0,0 is at upper left of the white page graphic
            'but for the printer 0,0 is at the non printable offset from the edge of the paper
            'so we need to translate 0, 0 to draw to the printer but not the preview picturebox
            'the first call here is for the preview graphic, then all calls after are to print
            If PrintingActive Then
                'values of the printable rectangle coordinates
                Dim paRectF As RectangleF
                paRectF = PrintDocument1.DefaultPageSettings.PrintableArea()
                e.Graphics.TranslateTransform(-paRectF.X, -paRectF.Y)
            End If
    
            Using bmp As Bitmap = New Bitmap(CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width), CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Height))
                Using g As Graphics = Graphics.FromImage(bmp)
                    g.DrawImage(theMetafile, 0, 0, bmp.Width, bmp.Height)
    
                    With e.Graphics
                        Dim scalefactor As Single
    
                        Dim ratio As Single = CSng(theMetafile.Width / theMetafile.Height)
    
                        'size to fit window maintaining aspect
                        Dim l, t, w, h As Integer
                        If ratio > .VisibleClipBounds.Width / .VisibleClipBounds.Height Then
                            w = CInt(.VisibleClipBounds.Width)
                            h = CInt(w / ratio)
                            t = CInt((.VisibleClipBounds.Height / 2) - (h / 2))
                        Else
                            h = CInt(.VisibleClipBounds.Height)
                            w = CInt(h * ratio)
                            l = CInt((.VisibleClipBounds.Width / 2) - (w / 2))
                        End If
    
                        'draw the image on the graphics
                        .DrawImage(bmp, l, t, w, h)
                    End With
                End Using
            End Using
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Try
                theMetafile = New Metafile("c:\bitmaps\tipple1.wmf")
    
    
                'show print preview with printdoc
                'prints if user clicks button on print preview
                PrintingActive = False              'set this false so preview coordinates are used for preview
                PrintPreviewDialog1.Document = PrintDocument1
                PrintPreviewDialog1.ShowDialog()
            Catch ex As Exception
                MsgBox("Problem Printing:" & Chr(13) & ex.Message, MsgBoxStyle.Exclamation)
            End Try
        End Sub
    
    End Class
    
    

    Friday, May 8, 2015 1:44 PM
  • Hello Tommy,

        I can see why both are working you are get the Metafile from a file and not memorystream. The emf starts as memorystream and sent the graphic.DrawImage. What you are saying is make bmp the same ratio as the emf then print that bmp and ratio will be the same..

    Shane

    Sunday, May 10, 2015 7:34 AM
  • Hello Tommy,

        I can see why both are working you are get the Metafile from a file and not memorystream. The emf starts as memorystream and sent the graphic.DrawImage. What you are saying is make bmp the same ratio as the emf then print that bmp and ratio will be the same..

    Shane


    Not quite.

    If I understood you last post, you were able to save the stream as an emf, you just cant draw from that stream like your first example.

    So first of all, I showed how to print a real metafile which is read the metafile to a metafile memory object:

         theMetafile = New Metafile("c:\bitmaps\tipple1.wmf")


    and then draw the true metafile using draw image.

         graphicobject.DrawImage(theMetafile, l, t, w, h)

    so all that is left if the size of the graphics object to draw on.

    A metafile has no defined "size" in pixels. It is a vector file. It can be any size.

    What is saved in the file are simply coordinates, and the scale is unity, more or less.

    So in the metafile (this is just my simplification) is say one line from coordinates (0.2, 0.2) - (0.7, 0.7).

    That metafile was created by capturing the GDI drawing from a graphics object. So maybe you draw a line using GDI on a picture box and captured that to a metafile. The GDI draw was:

         e.graphics.drawline(p, 20,20,70,70)

    and the picturebox size in pixels was 100 x 100

    so the Unit dimensions of the line are 20/100 = 0.2 or  (0.2, 0.2) - (0.7, 0.7) and that is save in the metafile. Not pixel x,y color= blue for all the pixels that make a line - as in a bitmap. When you blow up that bitmap all you get are more pixels blown up.

    Now when you redraw the metafile to a graphics object, it draws the line again and now it scales it to the new graphics object size.

    So if you draw to picturebox that is 200 x 200 you get a line from (40,40)-(140,140) on the graphic in pixels and on the screen this is a bitmap 200x200 with the pixels to make the line color changed.

    Follow?

    That is the infinite resolution of a vector file like metafile or an AutoCAD .DWG file.

    So that is how to print a metafile. Or draw it on a bitmap. And the printer paper is basically a bitmap, the printer prints dots. Just much smaller dpi than a bitmap on the screen.

    Now, you say you cant print your stream as a metafile but you can save it as one (although I am not convinced what you saved is a metafile, and not a bitmap).

    So now you should be able to read the metafile to a metafile object, not a bitmap, and then you have a real metafile in memory and you can draw that to screen or printer (a bitmap) with the high resolution of the line. I show how to do it directly first. And I show how to draw the metafile to a memory bitmap the size of the printer page and then copy the memory bitmap to the printer. If you make the bitmap large enough it will have the same resolution as the printer in pixels. So if your printer is 600 dpi and you paper is 11 inches high that is 6600 pixels high on the paper. So making a memory bitmap the size of the printer graphics object (printer.printablearea) you get the full resolution of the vector metafile.

    In the example, instead of a picturebox 200 x 200 you have the printer 5100 x 6600 pixels. I get the printer size using the printablearea and make a bitmap in memory and draw the metafile on it and copy the memory bitmap to the printer. Since the memory bitmap is the same size as the printer no loss of resolution.

    So my second example shows how to read the metafile you saved, make a bitmap in memory the size of the printer and draw the vector metafile on the memory bitmap. Then copy that to the printer by drawing it on the printer.

    If your saved file is a true metafile you will get the fine resolution you want. If it is really a bitmap, you will get a blown up bitmap which will be a fuzzy mess.

    Now, what I am thinking is you should be able to draw your file stream to the large bitmap and print that bitmap. Then you dont have to save the metafile first. Follow?

    What your are doing in your first example is drawing the stream to a metafile graphics object.

    ie you get an error here:

       Dim mf As Metafile = New Metafile(ms2, g.GetHdc)

    because you are attempting to  draw your ms2 stream to the metafile. What you need to do, this just hit me, is draw the memory stream to a memory bitmap graphics object, and capture that drawing as a metafile.

    That solution just hit me. Not that same as what I was saying with my two examples. Let me make an example. I will be back later today...

    Sunday, May 10, 2015 1:56 PM
  • This example shows how to create a true metafile. I will be back with a new solution. In the mean time see if you can spot the difference between this and what you did with your filestream.

    Imports System.Drawing.Imaging
    Imports System.Drawing.Drawing2D
    Public Class Form2
    
        Private Sub MetafileSave_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.ClientSize = New Size(400, 400)
    
        End Sub
        Private Sub MetafileSave_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
            DrawScene(e.Graphics)
    
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim filename As String
    
            filename = "c:\bitmaps\test1.wmf"
    
            Using GForm As Graphics = Me.CreateGraphics
                Dim hDC As IntPtr = GForm.GetHdc
                Using MF As New Metafile(filename, hDC, Me.ClientRectangle, MetafileFrameUnit.Pixel)
                    Using GMF As Graphics = Graphics.FromImage(MF)
    
                        DrawScene(GMF)
    
                    End Using
                End Using
            End Using
        End Sub
        Private Sub DrawScene(g As Graphics)
            Dim thescale, dx As Single
    
            thescale = 1
            dx = 0
    
            g.TranslateTransform(dx, dx)
            g.ScaleTransform(thescale, thescale)
    
            g.DrawRectangle(Pens.Red, New Rectangle(50, 50, 300, 300))
            g.DrawRectangle(Pens.Blue, New Rectangle(150, 150, 100, 100))
    
        End Sub
    End Class
    this is the metafile (shown in windows paint):

    Sunday, May 10, 2015 2:08 PM
  • You want to do something like this. Although this saves a file. We want it to go to the printer instead of saving it. I am trying to figure out how to do that. See if you can save your stream as a metafile this way. If so we will send it to a printer instead. Or you can open the metafile and print it direct with my above example. Hope you can follow what I am saying.

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            chart2.SaveImage(ms2, System.Drawing.Imaging.ImageFormat.Emf)
    
            Dim filename As String
    
            filename = "c:\bitmaps\test1.wmf"
    
            Using GForm As Graphics = Me.CreateGraphics
                Dim hDC As IntPtr = GForm.GetHdc
                Using MF As New Metafile(filename, hDC, Me.ClientRectangle, MetafileFrameUnit.Pixel)
                    Using GMF As Graphics = Graphics.FromImage(MF)
    
                        GMF.DrawImage(ms2)
    
                    End Using
                End Using
            End Using
        End Sub


    PS I will be back later today or tonight with a new solution. Study this and metafiles in the mean time.

    All you want to do is print the chart with as good of resolution as you can get right? I may get rid of your memory stream... we shall see.

    Sunday, May 10, 2015 2:24 PM
  • Good news and bad news. 

    Bad news is still the same problem. There is no ENCODER for metafile in .net so we cant create a memory metafile or some such thing, just read it from a discfile to a graphics object. ANd anyway, I am not sure how to capture the real chart gdi drawing to a metafile. So that went nowhere.

    We have to stick with creating a true metafile by saving it. Then reading that and sending it to the printer, just use my first example. And as you said you are already doing. You should get excellent results with that. But I am not sure you are saving a true metafile. 

    Good news is, I made an example with the other approach to make a big bitmap and print that.

    You can see that I make a giant size chart2 based on the screen and printer resolution. You can see the giant chart2 in the lower right of the image below (yours would not be visible). Then I capture the chart2 image to a bitmap. Next I size the bitmap to fit the printer page and then draw the bitmap on the printer graphics.

    I think it does quite well.

    There are details to work out. The chart clientsize.width should really be the chartarea.width I think but dont know. YOu need to size the fonts and whatever else you want. And of course if you make chart2 twice the size as I am doing it will look even better. But thats a big chart and I am not sure how big you can go before you get an error. You see the size original chart1 I have. If your chart is full screen and you want it to look the same on the paper you will need to adjust all the size things accordingly and experiment with it.

    So now you have two methods. Compare the tow and decide. If you are truly saving a real metafile of the chart graphics that should give the best result.

    If you are saving a bitmap, then this example should look 6x better.

    :)

    Option Strict On
    Imports System.Windows.Forms.DataVisualization.Charting
    Imports System.Drawing.Imaging
    Imports System.Drawing.Printing
    
    Public Class Form2
        Private WithEvents PrintDocument1 As PrintDocument = New PrintDocument
        Private PrintPreviewDialog1 As New PrintPreviewDialog
        Private PrintingActive As Boolean
    
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Chart2.Visible = False
    
            DrawChart(Chart1)
    
        End Sub
    
        Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
            Try
                'show print preview with printdoc
                'prints if user clicks button on print preview
                PrintingActive = False              'set this false so preview coordinates are used for preview
                PrintPreviewDialog1.Document = PrintDocument1
                PrintPreviewDialog1.ShowDialog()
            Catch ex As Exception
                MsgBox("Problem Printing:" & Chr(13) & ex.Message, MsgBoxStyle.Exclamation)
            End Try
        End Sub
    
        Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
            'for print preview the picturebox graphics coord 0,0 is at upper left of the white page graphic
            'but for the printer 0,0 is at the non printable offset from the edge of the paper
            'so we need to translate 0, 0 to draw to the printer but not the preview picturebox
            'the first call here is for the preview graphic, then all calls after are to print
            If PrintingActive Then
                'values of the printable rectangle coordinates
                Dim paRectF As RectangleF
                paRectF = PrintDocument1.DefaultPageSettings.PrintableArea()
                e.Graphics.TranslateTransform(-paRectF.X, -paRectF.Y)
            End If
    
            'determine the size ratio of the screen with the printer
            Dim r As Single
            Using g As Graphics = Me.CreateGraphics
                r = e.Graphics.DpiX / g.DpiX
            End Using
    
            Dim w As Integer = CInt(Chart1.ClientSize.Width * r)
            Dim h As Integer = CInt(Chart1.ClientSize.Height * r)
    
            'create a large chart and capture the image
            Chart2.ClientSize = New Size(w, h)
            DrawChart(Chart2)
    
            'create bitmap for the large chart image in memory and copy the bitmap to the printer
            Using bmp As Bitmap = New Bitmap(w, h)
    
                'capture the large chart image
                Chart2.DrawToBitmap(bmp, New Rectangle(0, 0, w, h))
    
                'print the large chart image
                Dim l, t As Integer
                Dim ratio As Single = CSng(bmp.Width / bmp.Height)
                With e.Graphics
                    'size to fit window maintaining aspect
                    If ratio > .VisibleClipBounds.Width / .VisibleClipBounds.Height Then
                        w = CInt(.VisibleClipBounds.Width)
                        h = CInt(w / ratio)
                        t = CInt((.VisibleClipBounds.Height / 2) - (h / 2))
                    Else
                        h = CInt(.VisibleClipBounds.Height)
                        w = CInt(h * ratio)
                        l = CInt((.VisibleClipBounds.Width / 2) - (w / 2))
                    End If
    
                    'draw the image on the graphics
                    .DrawImage(bmp, l, t, w, h)
                End With
            End Using
        End Sub
    
        Private Sub DrawChart(theChart As Chart)
            Dim theFontsize As Integer = CInt(theChart.ClientSize.Width / 40)
    
            'setup the chart
            With theChart.ChartAreas(0)
                .AxisX.Title = "X"
                .AxisX.MajorGrid.LineColor = Color.LightBlue
                .AxisX.Minimum = 0
                .AxisX.Interval = 20
                .AxisX.LabelStyle.Font = New Font("Arial", theFontSize)
                .AxisX.IsLabelAutoFit = False
    
                .AxisY.Title = "Y"
                .AxisY.MajorGrid.LineColor = Color.LightGray
                .AxisY.Minimum = 0
                .AxisY.LabelStyle.Font = New Font("Arial", theFontSize)
                .AxisY.IsLabelAutoFit = False
    
    
                .BackColor = Color.FloralWhite  'AntiqueWhite 'LightSkyBlue
                .BackSecondaryColor = Color.White
                .BackGradientStyle = GradientStyle.HorizontalCenter
                .BorderColor = Color.Blue
                .BorderDashStyle = ChartDashStyle.Solid
                .BorderWidth = 1
                .ShadowOffset = 2
            End With
    
            'draw the chart
            theChart.Series.Clear()
            theChart.Series.Add("Y = f(x)")
            With theChart.Series(0)
                .ChartType = DataVisualization.Charting.SeriesChartType.Line
                .BorderWidth = CInt(theChart.ClientSize.Width / 200)
                .Color = Color.Red
                .IsVisibleInLegend = False
    
                Dim y As Single
                For x = 0 To 100 Step 10
                    y = CSng(0.3 * x ^ 1.5)
                    .Points.AddXY(x, y)
                Next
            End With
        End Sub
    End Class
    

    Sunday, May 10, 2015 9:07 PM
  • Hi,

    I absolutely dont know if this is possible.

    cant you simple play the metafile to the printers graphics-object? (via EnumerateMetafile)? Like you would to get a bitmap from it?

    Regards,

      Thorsten

    Sunday, May 10, 2015 9:37 PM
  • Thornsten,

    I am just going by the articles in the first posts. It seems its not directly available for us in vb, in whatever version of .net they were using. Then they showed a couple of ways using api and another similar to yours. Maybe today that is not true?

    I don't really know.

    Can you print a chart by using a metafile so we get high vector style resolution?

    Sunday, May 10, 2015 9:38 PM
  • Hi,

    I absolutely dont know if this is possible.

    cant you simple play the metafile to the printers graphics-object? (via EnumerateMetafile)? Like you would to get a bitmap from it?

    Regards,

      Thorsten

    I don't know. But it seems to me when you mf = New Metafile, that is really a memory bitmap that was drawn using the metafile, the size of the object it was drawn on.

    Sunday, May 10, 2015 9:40 PM

  • Can you print a chart by using a metafile so we get high vector style resolution?

    I dont know, what I know is that you can get a graphics object from the metafile to draw onto.

    Regards,

      Thorsten

    Sunday, May 10, 2015 9:41 PM

  • Can you print a chart by using a metafile so we get high vector style resolution?

    I dont know, what I know is that you can get a graphics object from the metafile to draw onto.

    Regards,

      Thorsten

    Well the problem has two parts. First is this is using the image on a chart control. So how does one make a wmf from that?

    Second, well, nevermind, that is the problem. Jeffery was trying to serialize it as you see. I must admit I don't know that much about that but I really supect that is not a wmf but could be wrong.

    So if you can get a true wmf in memory of the chart then its a simple matter to print it.

    I was thinking I could capture the gdi drawing of the chart somehow, that is how you make a wmf. But I don't know how as we never have the graphics handle as vb draws the chart, just of the image on the screen or whatever save control image gives.

    Maybe you can crack it as you know those details better I think.

    Sunday, May 10, 2015 9:47 PM
  • Hi, you can create a new metafile that is a real metafile, since you can copy the content to a file (of type emf) with the winapi.

    But I dont know how to draw a chart to anything else than the chart-object or a bitmap... I'm exploring...

    Regards,

      Thorsten

    Sunday, May 10, 2015 9:56 PM

  • Can you print a chart by using a metafile so we get high vector style resolution?

    I dont know, what I know is that you can get a graphics object from the metafile to draw onto.

    Regards,

      Thorsten

    Well the problem has two parts. First is this is using the image on a chart control. So how does one make a wmf from that?

    Second, well, nevermind, that is the problem. Jeffery was trying to serialize it as you see. I must admit I don't know that much about that but I really supect that is not a wmf but could be wrong.

    So if you can get a true wmf in memory of the chart then its a simple matter to print it.

    I was thinking I could capture the gdi drawing of the chart somehow, that is how you make a wmf. But I don't know how as we never have the graphics handle as vb draws the chart, just of the image on the screen or whatever save control image gives.

    Maybe you can crack it as you know those details better I think.

    PS The articles discuss serializing a metafile. And there it says Microsoft never bought the rights to the metafile encoder for vb, or some .net version. They were going around it because apparently the win32 gdi has rights. But that is for serializing.

    If I have a wmf I can print it as my first example.

    Jeffery is trying to get a high res printout of the chart, by serializing a wmf of it and printing that. I don't think serializing makes a metafile that is why Jeffery gets an error when he tries.

    So the problem is still how to make a metafile of a chart control graphic.

    PS I am not sayin I understand it. Just that I cant do it.

    Sunday, May 10, 2015 10:01 PM
  • Hi,

    this works:

    Public Class Form1 Inherits Form Public Sub New() InitializeComponent() End Sub Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) If Me.BackgroundImage IsNot Nothing Then Me.BackgroundImage.Dispose() End If End Sub Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click Dim m As Metafile Using stream As New MemoryStream() Using offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero) Dim deviceContextHandle As IntPtr = offScreenBufferGraphics.GetHdc() m = New Metafile(stream, deviceContextHandle, New RectangleF(0, 0, 256, 256), MetafileFrameUnit.Pixel, EmfType.EmfPlusOnly) offScreenBufferGraphics.ReleaseHdc() End Using End Using Using stream2 As New MemoryStream() Chart1.SaveImage(stream2, ChartImageFormat.Emf) Me.BackColor = Color.Green Dim mtbc As New MetaFileToBitmapConverter() stream2.Position = 0 Me.BackgroundImage = mtbc.GetBitmapFromMetafile(stream2, Me.ClientSize.Width, Me.ClientSize.Height) mtbc.Dispose() End Using End Sub Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load DrawChart(Chart1) End Sub Private Sub DrawChart(theChart As Chart) Dim theFontsize As Integer = CInt(theChart.ClientSize.Width / 40) 'setup the chart With theChart.ChartAreas(0) .AxisX.Title = "X" .AxisX.MajorGrid.LineColor = Color.LightBlue .AxisX.Minimum = 0 .AxisX.Interval = 20 .AxisX.LabelStyle.Font = New Font("Arial", theFontsize) .AxisX.IsLabelAutoFit = False .AxisY.Title = "Y" .AxisY.MajorGrid.LineColor = Color.LightGray .AxisY.Minimum = 0 .AxisY.LabelStyle.Font = New Font("Arial", theFontsize) .AxisY.IsLabelAutoFit = False .BackColor = Color.FloralWhite 'AntiqueWhite 'LightSkyBlue .BackSecondaryColor = Color.White .BackGradientStyle = GradientStyle.HorizontalCenter .BorderColor = Color.Blue .BorderDashStyle = ChartDashStyle.Solid .BorderWidth = 1 .ShadowOffset = 2 End With 'draw the chart theChart.Series.Clear() theChart.Series.Add("Y = f(x)") With theChart.Series(0) .ChartType = DataVisualization.Charting.SeriesChartType.Line .BorderWidth = CInt(theChart.ClientSize.Width / 200) .Color = Color.Red .IsVisibleInLegend = False Dim y As Single For x = 0 To 100 Step 10 y = CSng(0.3 * x ^ 1.5) .Points.AddXY(x, y) Next End With End Sub End Class

    'dont know where I have it from... somewhere from an example.. Public Class MetaFileToBitmapConverter Implements IDisposable Private _metaFile As Metafile = Nothing Public Function GetBitmapFromMetafile(FileName As MemoryStream, width As Integer, height As Integer) As Bitmap _metaFile = New Metafile(FileName) Dim bmpOut As New Bitmap(width, height) 'try here to use the prointers graphics Using g As Graphics = Graphics.FromImage(bmpOut) Try g.EnumerateMetafile(_metaFile, New Rectangle(0, 0, width, height), AddressOf DrawRecords) Catch End Try End Using _metaFile.Dispose() Return bmpOut End Function Private Function DrawRecords(recordType As EmfPlusRecordType, flags As Integer, dataSize As Integer, data As IntPtr, callbackData As PlayRecordCallback) As Boolean Dim data_array As Byte() = Nothing If Not data.Equals(IntPtr.Zero) Then data_array = New Byte(dataSize - 1) {} Marshal.Copy(data, data_array, 0, dataSize) End If _metaFile.PlayRecord(recordType, flags, dataSize, data_array) Return True End Function Public Sub Dispose() Implements IDisposable.Dispose If _metaFile IsNot Nothing Then _metaFile.Dispose() End If End Sub End Class


    Regards,

      Thorsten

    Sunday, May 10, 2015 10:06 PM

  • 'dont know where I have it from... somewhere from an example..

    ...

    from here:

    https://social.msdn.microsoft.com/Forums/en-US/f45e12af-1f25-45f7-837a-3d70e0367cfc/improve-metafile-drawing-performance-issue?forum=netfxbcl

    https://msdn.microsoft.com/en-us/library/system.drawing.imaging.metafile.playrecord.aspx?f=255&MSPPError=-2147217396

    Sunday, May 10, 2015 10:10 PM

  • 'dont know where I have it from... somewhere from an example..

    ...

    from here:

    https://social.msdn.microsoft.com/Forums/en-US/f45e12af-1f25-45f7-837a-3d70e0367cfc/improve-metafile-drawing-performance-issue?forum=netfxbcl

    https://msdn.microsoft.com/en-us/library/system.drawing.imaging.metafile.playrecord.aspx?f=255&MSPPError=-2147217396

    John Wein taught me every thing I know about metafiles in.net. Which is not that much.

    I put it into my above routine but not sure I am doing it correctly?

    It looks good, but still kinda looks like a bitmap. I am not sure. There is some issue with the plot line but I suspect that is just some detail.

    Did you try printing it?

        Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
            'for print preview the picturebox graphics coord 0,0 is at upper left of the white page graphic
            'but for the printer 0,0 is at the non printable offset from the edge of the paper
            'so we need to translate 0, 0 to draw to the printer but not the preview picturebox
            'the first call here is for the preview graphic, then all calls after are to print
            If PrintingActive Then
                'values of the printable rectangle coordinates
                Dim paRectF As RectangleF
                paRectF = PrintDocument1.DefaultPageSettings.PrintableArea()
                e.Graphics.TranslateTransform(-paRectF.X, -paRectF.Y)
            End If
    
            Dim m As Metafile
    
            Using stream As New MemoryStream()
                Using offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero)
                    Dim deviceContextHandle As IntPtr = offScreenBufferGraphics.GetHdc()
    
                    m = New Metafile(stream, deviceContextHandle, New RectangleF(0, 0, 256, 256), MetafileFrameUnit.Pixel, EmfType.EmfPlusOnly)
    
                    offScreenBufferGraphics.ReleaseHdc()
                End Using
            End Using
    
            Using stream2 As New MemoryStream()
                Chart1.SaveImage(stream2, ChartImageFormat.Emf)
    
                Me.BackColor = Color.Green
                Dim mtbc As New MetaFileToBitmapConverter()
                stream2.Position = 0
    
                With e.Graphics
                    Dim w As Integer = .VisibleClipBounds.Width
                    Dim h As Integer = .VisibleClipBounds.Height
    
                    Dim bmp As Bitmap = New Bitmap(w, h)
    
                    bmp = mtbc.GetBitmapFromMetafile(stream2, Me.ClientSize.Width, Me.ClientSize.Height)
    
                    mtbc.Dispose()
    
                    'draw the image on the graphics
                    .DrawImage(bmp, 0, 0, w, h)
                    bmp.Dispose()
                End With
            End Using
        End Sub
    
    End Class

    Edit: removed resize, new preview image.


    Sunday, May 10, 2015 10:54 PM
  • PS this is what my form chart looks like.

    And this is the BIG chart method printed to compare with the above wmf method.

    Sunday, May 10, 2015 11:08 PM
  • Hi,

    well you print a bitmap...

    I thought, we could use the graphics object of the PrintPageEventArgs, but my printpreview is always empty...

    But here is said that it at least prints correctly to the printer...

    https://social.msdn.microsoft.com/Forums/de-DE/a4e7487b-b687-4cf1-ac42-de25444bf532/drawing-a-metafile-to-a-printdocument-using-printpreview?forum=winforms

    (first post)

    code I tested with:

    Public Class Form1
        Inherits Form
    
        Dim _stream2 As MemoryStream = Nothing
    
        Public Sub New()
            InitializeComponent()
        End Sub
    
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs)
            If Me.BackgroundImage IsNot Nothing Then
                Me.BackgroundImage.Dispose()
            End If
        End Sub
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim m As Metafile
    
            Using stream As New MemoryStream()
                Using offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero)
                    Dim deviceContextHandle As IntPtr = offScreenBufferGraphics.GetHdc()
    
                    m = New Metafile(stream, deviceContextHandle, New RectangleF(0, 0, 256, 256), MetafileFrameUnit.Pixel, EmfType.EmfPlusOnly)
    
                    offScreenBufferGraphics.ReleaseHdc()
                End Using
            End Using
    
            Using stream2 As New MemoryStream()
                Chart1.SaveImage(stream2, ChartImageFormat.Emf)
    
                Dim mtbc As New MetaFileToBitmapConverter()
                stream2.Position = 0
                _stream2 = New MemoryStream(stream2.GetBuffer())
                _stream2.Position = 0
                Me.BackgroundImage = mtbc.GetBitmapFromMetafile(stream2, Me.ClientSize.Width, Me.ClientSize.Height)
    
                Me.PrintPreviewControl1.Document = Me.PrintDocument1
                mtbc.Dispose()
            End Using
        End Sub
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            DrawChart(Chart1)
        End Sub
    
        Private Sub DrawChart(theChart As Chart)
            Dim theFontsize As Integer = CInt(theChart.ClientSize.Width / 40)
    
            'setup the chart
            With theChart.ChartAreas(0)
                .AxisX.Title = "X"
                .AxisX.MajorGrid.LineColor = Color.LightBlue
                .AxisX.Minimum = 0
                .AxisX.Interval = 20
                .AxisX.LabelStyle.Font = New Font("Arial", theFontsize)
                .AxisX.IsLabelAutoFit = False
    
                .AxisY.Title = "Y"
                .AxisY.MajorGrid.LineColor = Color.LightGray
                .AxisY.Minimum = 0
                .AxisY.LabelStyle.Font = New Font("Arial", theFontsize)
                .AxisY.IsLabelAutoFit = False
    
    
                .BackColor = Color.FloralWhite  'AntiqueWhite 'LightSkyBlue
                .BackSecondaryColor = Color.White
                .BackGradientStyle = GradientStyle.HorizontalCenter
                .BorderColor = Color.Blue
                .BorderDashStyle = ChartDashStyle.Solid
                .BorderWidth = 1
                .ShadowOffset = 2
            End With
    
            'draw the chart
            theChart.Series.Clear()
            theChart.Series.Add("Y = f(x)")
            With theChart.Series(0)
                .ChartType = DataVisualization.Charting.SeriesChartType.Line
                .BorderWidth = CInt(theChart.ClientSize.Width / 200)
                .Color = Color.Red
                .IsVisibleInLegend = False
    
                Dim y As Single
                For x = 0 To 100 Step 10
                    y = CSng(0.3 * x ^ 1.5)
                    .Points.AddXY(x, y)
                Next
            End With
        End Sub
    
        Private Sub PrintDocument1_PrintPage(sender As System.Object, ev As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
            PrintDocument1.OriginAtMargins = False
    
            Dim mtbc As New MetaFileToBitmapConverter()
            _stream2.Position = 0
            mtbc.PrintMetafile(_stream2, Me.ClientSize.Width, Me.ClientSize.Height, ev)
            ev.HasMorePages = False
        End Sub
    
    
        Private Sub Form1_FormClosing_1(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
            If Not _stream2 Is Nothing Then
                _stream2.Dispose()
            End If
        End Sub
    End Class
    
    Public Class MetaFileToBitmapConverter
        Implements IDisposable
        Private _metaFile As Metafile = Nothing
    
        Public Function GetBitmapFromMetafile(FileName As MemoryStream, width As Integer, height As Integer) As Bitmap
            _metaFile = New Metafile(FileName)
    
            Dim bmpOut As New Bitmap(width, height)
            'try here to use the prointers graphics
            Using g As Graphics = Graphics.FromImage(bmpOut)
                Try
                    g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                    g.EnumerateMetafile(_metaFile, New Rectangle(0, 0, width, height), AddressOf DrawRecords)
    
                Catch
                End Try
            End Using
    
            _metaFile.Dispose()
    
            Return bmpOut
        End Function
    
        Public Sub PrintMetafile(FileName As MemoryStream, width As Integer, height As Integer, ByRef ev As Printing.PrintPageEventArgs)
            _metaFile = New Metafile(FileName)
    
            Dim g As Graphics = ev.Graphics
            Try
                g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                g.EnumerateMetafile(_metaFile, New Rectangle(0, 0, width, height), AddressOf DrawRecords)
    
                'g.DrawImage(_metaFile, 20, 20)
            Catch es As Exception
                MessageBox.Show(es.Message)
            End Try
    
            'g.FillRectangle(Brushes.Blue, New Rectangle(0, 0, width, height))
            _metaFile.Dispose()
        End Sub
    
        Private Function DrawRecords(recordType As EmfPlusRecordType, flags As Integer, dataSize As Integer, data As IntPtr, callbackData As PlayRecordCallback) As Boolean
            Dim data_array As Byte() = Nothing
    
            If Not data.Equals(IntPtr.Zero) Then
                data_array = New Byte(dataSize - 1) {}
                Marshal.Copy(data, data_array, 0, dataSize)
            End If
    
            _metaFile.PlayRecord(recordType, flags, dataSize, data_array)
    
            Return True
        End Function
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If _metaFile IsNot Nothing Then
                _metaFile.Dispose()
            End If
        End Sub
    End Class



    Sunday, May 10, 2015 11:21 PM
  • PS I left some resizing code in the wmf print example above that should have been removed. I have removed it and show a new preview image where it fits better.

    Sunday, May 10, 2015 11:25 PM
  • PS I left some resizing code in the wmf print example above that should have been removed. I have removed it and show a new preview image where it fits better.


    Well, actually, it was doing better with the resizing. Now printed it definitely looks like a bitmap. So I am not sure if I am doing the wmf right.
    Sunday, May 10, 2015 11:29 PM
  • Hi Tommy,

    I think the best is to draw just the image (as JohnWein (I also learned a lot from him and his messages) says in the linked thread). Setting the size to whatever needed...

    So, your above post seems to be the optimum to get, IMHO.

    Regards,

      Thorsten


    Sunday, May 10, 2015 11:36 PM
  • Hi Tommy,

    I think the best is to draw just the image (as JohnWein (I also learned a lot from him and his messages) says in the linked thread). Setting the size to whatever needed...

    So, your above post seems to be the optimum to get, IMHO.

    Regards,

      Thorsten


    Not sure I follow.

    I think I got your last example working. But its still a bitmap when you print it.

    You see, I think you can draw the metafile to a bitmap, but that is all you can do with it. So once you draw it its a bitmap. The we are just copying that to the printer. But I am not sure I understand it or what you are saying.

    I don't know streaming or enumerating so I cant do much with it.

    Anyway, this is your last example. It has improved but still prints like a bitmap although the preview looks better.

    Imports System.Windows.Forms.DataVisualization.Charting
    Imports System.Drawing.Imaging
    Imports System.IO
    Imports System.Drawing.Printing
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        Inherits Form
        Dim _stream2 As MemoryStream = Nothing
        Private WithEvents PrintDocument1 As PrintDocument = New PrintDocument
        Private PrintPreviewControl1 As New PrintPreviewDialog
        Private PrintingActive As Boolean
    
        Public Sub New()
            InitializeComponent()
        End Sub
    
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs)
            If Me.BackgroundImage IsNot Nothing Then
                Me.BackgroundImage.Dispose()
            End If
        End Sub
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Me.PrintPreviewControl1.Document = Me.PrintDocument1
            PrintPreviewControl1.ShowDialog()
    
        End Sub
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    
    
            DrawChart(Chart1)
        End Sub
    
        Private Sub DrawChart(theChart As Chart)
            Dim theFontsize As Integer = CInt(theChart.ClientSize.Width / 40)
    
            'setup the chart
            With theChart.ChartAreas(0)
                .AxisX.Title = "X"
                .AxisX.MajorGrid.LineColor = Color.LightBlue
                .AxisX.Minimum = 0
                .AxisX.Interval = 20
                .AxisX.LabelStyle.Font = New Font("Arial", theFontsize)
                .AxisX.IsLabelAutoFit = False
    
                .AxisY.Title = "Y"
                .AxisY.MajorGrid.LineColor = Color.LightGray
                .AxisY.Minimum = 0
                .AxisY.LabelStyle.Font = New Font("Arial", theFontsize)
                .AxisY.IsLabelAutoFit = False
    
    
                .BackColor = Color.FloralWhite  'AntiqueWhite 'LightSkyBlue
                .BackSecondaryColor = Color.White
                .BackGradientStyle = GradientStyle.HorizontalCenter
                .BorderColor = Color.Blue
                .BorderDashStyle = ChartDashStyle.Solid
                .BorderWidth = 1
                .ShadowOffset = 2
            End With
    
            'draw the chart
            theChart.Series.Clear()
            theChart.Series.Add("Y = f(x)")
            With theChart.Series(0)
                .ChartType = DataVisualization.Charting.SeriesChartType.Line
                .BorderWidth = CInt(theChart.ClientSize.Width / 200)
                .Color = Color.Red
                .IsVisibleInLegend = False
    
                Dim y As Single
                For x = 0 To 100 Step 10
                    y = CSng(0.3 * x ^ 1.5)
                    .Points.AddXY(x, y)
                Next
            End With
        End Sub
    
        Private Sub PrintDocument1_PrintPage(sender As System.Object, ev As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
            PrintDocument1.OriginAtMargins = False
    
            Dim m As Metafile
    
            Using stream As New MemoryStream()
                Using offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero)
                    Dim deviceContextHandle As IntPtr = offScreenBufferGraphics.GetHdc()
    
                    m = New Metafile(stream, deviceContextHandle, New RectangleF(0, 0, 256, 256), MetafileFrameUnit.Pixel, EmfType.EmfPlusOnly)
    
                    offScreenBufferGraphics.ReleaseHdc()
                End Using
            End Using
    
            Using stream2 As New MemoryStream()
                Chart1.SaveImage(stream2, ChartImageFormat.Emf)
    
                Dim mtbc As New MetaFileToBitmapConverter()
                stream2.Position = 0
                _stream2 = New MemoryStream(stream2.GetBuffer())
                _stream2.Position = 0
                mtbc.PrintMetafile(_stream2, ev)
    
                mtbc.Dispose()
            End Using
    
            'ev.HasMorePages = False
        End Sub
    
    
        Private Sub Form1_FormClosing_1(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
            If Not _stream2 Is Nothing Then
                _stream2.Dispose()
            End If
        End Sub
    End Class
    
    Public Class MetaFileToBitmapConverter
        Implements IDisposable
        Private _metaFile As Metafile = Nothing
    
        Public Function GetBitmapFromMetafile(FileName As MemoryStream, width As Integer, height As Integer) As Bitmap
            _metaFile = New Metafile(FileName)
    
            Dim bmpOut As New Bitmap(width, height)
            'try here to use the prointers graphics
            Using g As Graphics = Graphics.FromImage(bmpOut)
                Try
                    g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                    g.EnumerateMetafile(_metaFile, New Rectangle(0, 0, width, height), AddressOf DrawRecords)
    
                Catch
                End Try
            End Using
    
            _metaFile.Dispose()
    
            Return bmpOut
        End Function
    
        Public Sub PrintMetafile(FileName As MemoryStream, ByRef ev As Printing.PrintPageEventArgs)
            _metaFile = New Metafile(FileName)
    
            Dim g As Graphics = ev.Graphics
            Try
                g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                g.EnumerateMetafile(_metaFile, New Rectangle(ev.MarginBounds.Left, ev.MarginBounds.Top, ev.MarginBounds.Width, ev.MarginBounds.Height), AddressOf DrawRecords)
                g.DrawImage(_metaFile, New Rectangle(ev.MarginBounds.Left, ev.MarginBounds.Top, ev.MarginBounds.Width, ev.MarginBounds.Height))
            Catch es As Exception
                MessageBox.Show(es.Message)
            End Try
    
            _metaFile.Dispose()
        End Sub
    
        Private Function DrawRecords(recordType As EmfPlusRecordType, flags As Integer, dataSize As Integer, data As IntPtr, callbackData As PlayRecordCallback) As Boolean
            Dim data_array As Byte() = Nothing
    
            If Not data.Equals(IntPtr.Zero) Then
                data_array = New Byte(dataSize - 1) {}
                Marshal.Copy(data, data_array, 0, dataSize)
            End If
    
            _metaFile.PlayRecord(recordType, flags, dataSize, data_array)
    
            Return True
        End Function
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If _metaFile IsNot Nothing Then
                _metaFile.Dispose()
            End If
        End Sub
    End Class
    
    

    Edit: corrected error causing funny remants on the borders.
    Monday, May 11, 2015 12:11 AM
  • Well, actually now that I look at the printout again it looks pretty darn good.

    I think we have it !!!!

    You confirm.

    Monday, May 11, 2015 12:14 AM
  • Well, actually now that I look at the printout again it looks pretty darn good.

    I think we have it !!!!

    You confirm.

    Ok I corrected the last example of printing the wmf method and it seems to work great!

    Monday, May 11, 2015 12:22 AM
  • Yes, it looks good, but you do not need to enumerate the metafile now, just call g.DrawImage in the printmetafile class

    or just as you did above:

    Public Class Form1
        Inherits Form
    
        Dim _stream2 As MemoryStream = Nothing
    
        Public Sub New()
            InitializeComponent()
        End Sub
    
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs)
            If Me.BackgroundImage IsNot Nothing Then
                Me.BackgroundImage.Dispose()
            End If
        End Sub
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim m As Metafile
    
            Using stream As New MemoryStream()
                Using offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero)
                    Dim deviceContextHandle As IntPtr = offScreenBufferGraphics.GetHdc()
    
                    m = New Metafile(stream, deviceContextHandle, New RectangleF(0, 0, 256, 256), MetafileFrameUnit.Pixel, EmfType.EmfPlusOnly)
    
                    offScreenBufferGraphics.ReleaseHdc()
                End Using
            End Using
    
            Using stream2 As New MemoryStream()
                Chart1.SaveImage(stream2, ChartImageFormat.Emf)
    
                Dim mtbc As New MetaFileToBitmapConverter()
                stream2.Position = 0
                _stream2 = New MemoryStream(stream2.GetBuffer())
                _stream2.Position = 0
                'Me.BackgroundImage = mtbc.GetBitmapFromMetafile(stream2, Me.ClientSize.Width, Me.ClientSize.Height)
    
                Me.PrintPreviewDialog1.ShowDialog()
    
                mtbc.Dispose()
            End Using
        End Sub
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            DrawChart(Chart1)
        End Sub
    
        Private Sub DrawChart(theChart As Chart)
            Dim theFontsize As Integer = CInt(theChart.ClientSize.Width / 40)
    
            'setup the chart
            With theChart.ChartAreas(0)
                .AxisX.Title = "X"
                .AxisX.MajorGrid.LineColor = Color.LightBlue
                .AxisX.Minimum = 0
                .AxisX.Interval = 20
                .AxisX.LabelStyle.Font = New Font("Arial", theFontsize)
                .AxisX.IsLabelAutoFit = False
    
                .AxisY.Title = "Y"
                .AxisY.MajorGrid.LineColor = Color.LightGray
                .AxisY.Minimum = 0
                .AxisY.LabelStyle.Font = New Font("Arial", theFontsize)
                .AxisY.IsLabelAutoFit = False
    
    
                .BackColor = Color.FloralWhite  'AntiqueWhite 'LightSkyBlue
                .BackSecondaryColor = Color.White
                .BackGradientStyle = GradientStyle.HorizontalCenter
                .BorderColor = Color.Blue
                .BorderDashStyle = ChartDashStyle.Solid
                .BorderWidth = 1
                .ShadowOffset = 2
            End With
    
            'draw the chart
            theChart.Series.Clear()
            theChart.Series.Add("Y = f(x)")
            With theChart.Series(0)
                .ChartType = DataVisualization.Charting.SeriesChartType.Line
                .BorderWidth = CInt(theChart.ClientSize.Width / 200)
                .Color = Color.Red
                .IsVisibleInLegend = False
    
                Dim y As Single
                For x = 0 To 100 Step 10
                    y = CSng(0.3 * x ^ 1.5)
                    .Points.AddXY(x, y)
                Next
            End With
        End Sub
    
        Private Sub PrintDocument1_PrintPage(sender As System.Object, ev As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
            PrintDocument1.OriginAtMargins = False
    
            Dim mtbc As New MetaFileToBitmapConverter()
            _stream2.Seek(0, 0)
            _stream2.Position = 0
            Dim bmp As Bitmap = mtbc.GetBitmapFromMetafile(_stream2, Me.ClientSize.Width, Me.ClientSize.Height)
            ev.Graphics.DrawImage(bmp, ev.MarginBounds)
            bmp.Dispose()
            ev.HasMorePages = False
        End Sub
    
        Private Sub Form1_FormClosing_1(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
            If Not _stream2 Is Nothing Then
                _stream2.Dispose()
            End If
        End Sub
    End Class
    
    Public Class MetaFileToBitmapConverter
        Implements IDisposable
        Private _metaFile As Metafile = Nothing
    
        Public Function GetBitmapFromMetafile(FileName As MemoryStream, width As Integer, height As Integer) As Bitmap
            _metaFile = New Metafile(FileName)
    
            Dim bmpOut As New Bitmap(width, height)
            'try here to use the prointers graphics
            Using g As Graphics = Graphics.FromImage(bmpOut)
                Try
                    g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                    g.EnumerateMetafile(_metaFile, New Rectangle(0, 0, width, height), AddressOf DrawRecords)
    
                Catch
                End Try
            End Using
    
            _metaFile.Dispose()
    
            Return bmpOut
        End Function
    
        Private Function DrawRecords(recordType As EmfPlusRecordType, flags As Integer, dataSize As Integer, data As IntPtr, callbackData As PlayRecordCallback) As Boolean
            Dim data_array As Byte() = Nothing
    
            If Not data.Equals(IntPtr.Zero) Then
                data_array = New Byte(dataSize - 1) {}
                Marshal.Copy(data, data_array, 0, dataSize)
            End If
    
            _metaFile.PlayRecord(recordType, flags, dataSize, data_array)
    
            Return True
        End Function
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If _metaFile IsNot Nothing Then
                _metaFile.Dispose()
            End If
        End Sub
    End Class

    Regards,

      Thorsten



    Monday, May 11, 2015 12:22 AM
  • Thorsten,

    Well, sorry, I cant get your last example to work and I am not sure what you meant or changed. Not sure if I am messing it up.

    It is most helpful if you include all the imports and the declares so we don't have to add them.

    :)

    Monday, May 11, 2015 1:02 AM
  • Hi,

    ok, create anew WinForms project and add a Reference to the System.Windows.Forms.DataVisualization dll

    Then copy this code: (while I will drink some coffee :-) )

    Its just almost the same as you did above somewhere

    Imports System.Drawing.Imaging
    Imports System.Windows.Forms.DataVisualization.Charting
    Imports System.IO
    Imports System.Runtime.InteropServices
    
    Public Class Form1
        Inherits Form
    
        Friend WithEvents Chart1 As System.Windows.Forms.DataVisualization.Charting.Chart
        Friend WithEvents Button1 As System.Windows.Forms.Button
        Friend WithEvents PrintDocument1 As System.Drawing.Printing.PrintDocument
        Friend WithEvents PrintPreviewDialog1 As System.Windows.Forms.PrintPreviewDialog
    
        Dim _stream2 As MemoryStream = Nothing
    
        Public Sub New()
            InitializeComponent()
    
            Dim ChartArea1 As System.Windows.Forms.DataVisualization.Charting.ChartArea = New System.Windows.Forms.DataVisualization.Charting.ChartArea()
            Dim Legend1 As System.Windows.Forms.DataVisualization.Charting.Legend = New System.Windows.Forms.DataVisualization.Charting.Legend()
            Dim Series1 As System.Windows.Forms.DataVisualization.Charting.Series = New System.Windows.Forms.DataVisualization.Charting.Series()
            Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(Form1))
            Me.Chart1 = New System.Windows.Forms.DataVisualization.Charting.Chart()
            Me.Button1 = New System.Windows.Forms.Button()
            Me.PrintDocument1 = New System.Drawing.Printing.PrintDocument()
            Me.PrintPreviewDialog1 = New System.Windows.Forms.PrintPreviewDialog()
            '
            'Chart1
            '
            ChartArea1.Name = "ChartArea1"
            Me.Chart1.ChartAreas.Add(ChartArea1)
            Legend1.Name = "Legend1"
            Me.Chart1.Legends.Add(Legend1)
            Me.Chart1.Location = New System.Drawing.Point(52, 54)
            Me.Chart1.Name = "Chart1"
            Series1.ChartArea = "ChartArea1"
            Series1.Legend = "Legend1"
            Series1.Name = "Series1"
            Me.Chart1.Series.Add(Series1)
            Me.Chart1.Size = New System.Drawing.Size(300, 300)
            Me.Chart1.TabIndex = 0
            Me.Chart1.Text = "Chart1"
            '
            'Button1
            '
            Me.Button1.Location = New System.Drawing.Point(836, 489)
            Me.Button1.Name = "Button1"
            Me.Button1.Size = New System.Drawing.Size(75, 23)
            Me.Button1.TabIndex = 1
            Me.Button1.Text = "Button1"
            Me.Button1.UseVisualStyleBackColor = True
            '
            'PrintDocument1
            '
            '
            'PrintPreviewDialog1
            '
            Me.PrintPreviewDialog1.AutoScrollMargin = New System.Drawing.Size(0, 0)
            Me.PrintPreviewDialog1.AutoScrollMinSize = New System.Drawing.Size(0, 0)
            Me.PrintPreviewDialog1.ClientSize = New System.Drawing.Size(400, 300)
            Me.PrintPreviewDialog1.Document = Me.PrintDocument1
            Me.PrintPreviewDialog1.Enabled = True
            Me.PrintPreviewDialog1.Name = "PrintPreviewDialog1"
            Me.PrintPreviewDialog1.Visible = False
            '
            'Form1
            '
            Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
            Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
            Me.ClientSize = New System.Drawing.Size(981, 696)
            Me.Controls.Add(Me.Button1)
            Me.Controls.Add(Me.Chart1)
            Me.Name = "Form1"
            Me.Text = "Form1"
        End Sub
    
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
            If Me.BackgroundImage IsNot Nothing Then
                Me.BackgroundImage.Dispose()
            End If
        End Sub
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim m As Metafile
    
            Using stream As New MemoryStream()
                Using offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero)
                    Dim deviceContextHandle As IntPtr = offScreenBufferGraphics.GetHdc()
    
                    m = New Metafile(stream, deviceContextHandle, New RectangleF(0, 0, 256, 256), MetafileFrameUnit.Pixel, EmfType.EmfPlusOnly)
    
                    offScreenBufferGraphics.ReleaseHdc()
                End Using
            End Using
    
            Using stream2 As New MemoryStream()
                Chart1.SaveImage(stream2, ChartImageFormat.Emf)
    
                Dim mtbc As New MetaFileToBitmapConverter()
                stream2.Position = 0
                _stream2 = New MemoryStream(stream2.GetBuffer())
                _stream2.Position = 0
                'Me.BackgroundImage = mtbc.GetBitmapFromMetafile(stream2, Me.ClientSize.Width, Me.ClientSize.Height)
    
                Me.PrintPreviewDialog1.ShowDialog()
    
                mtbc.Dispose()
            End Using
        End Sub
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            DrawChart(Chart1)
        End Sub
    
        Private Sub DrawChart(theChart As Chart)
            Dim theFontsize As Integer = CInt(theChart.ClientSize.Width / 40)
    
            'setup the chart
            With theChart.ChartAreas(0)
                .AxisX.Title = "X"
                .AxisX.MajorGrid.LineColor = Color.LightBlue
                .AxisX.Minimum = 0
                .AxisX.Interval = 20
                .AxisX.LabelStyle.Font = New Font("Arial", theFontsize)
                .AxisX.IsLabelAutoFit = False
    
                .AxisY.Title = "Y"
                .AxisY.MajorGrid.LineColor = Color.LightGray
                .AxisY.Minimum = 0
                .AxisY.LabelStyle.Font = New Font("Arial", theFontsize)
                .AxisY.IsLabelAutoFit = False
    
    
                .BackColor = Color.FloralWhite  'AntiqueWhite 'LightSkyBlue
                .BackSecondaryColor = Color.White
                .BackGradientStyle = GradientStyle.HorizontalCenter
                .BorderColor = Color.Blue
                .BorderDashStyle = ChartDashStyle.Solid
                .BorderWidth = 1
                .ShadowOffset = 2
            End With
    
            'draw the chart
            theChart.Series.Clear()
            theChart.Series.Add("Y = f(x)")
            With theChart.Series(0)
                .ChartType = DataVisualization.Charting.SeriesChartType.Line
                .BorderWidth = CInt(theChart.ClientSize.Width / 200)
                .Color = Color.Red
                .IsVisibleInLegend = False
    
                Dim y As Single
                For x = 0 To 100 Step 10
                    y = CSng(0.3 * x ^ 1.5)
                    .Points.AddXY(x, y)
                Next
            End With
        End Sub
    
        Private Sub PrintDocument1_PrintPage(sender As System.Object, ev As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
            PrintDocument1.OriginAtMargins = False
    
            Dim mtbc As New MetaFileToBitmapConverter()
            _stream2.Seek(0, 0)
            _stream2.Position = 0
            Dim bmp As Bitmap = mtbc.GetBitmapFromMetafile(_stream2, Me.ClientSize.Width, Me.ClientSize.Height)
            ev.Graphics.DrawImage(bmp, ev.MarginBounds)
            bmp.Dispose()
            ev.HasMorePages = False
        End Sub
    
        Private Sub Form1_FormClosing_1(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
            If Not _stream2 Is Nothing Then
                _stream2.Dispose()
            End If
        End Sub
    End Class
    
    Public Class MetaFileToBitmapConverter
        Implements IDisposable
        Private _metaFile As Metafile = Nothing
    
        Public Function GetBitmapFromMetafile(FileName As MemoryStream, width As Integer, height As Integer) As Bitmap
            _metaFile = New Metafile(FileName)
    
            Dim bmpOut As New Bitmap(width, height)
            'try here to use the prointers graphics
            Using g As Graphics = Graphics.FromImage(bmpOut)
                Try
                    g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                    g.EnumerateMetafile(_metaFile, New Rectangle(0, 0, width, height), AddressOf DrawRecords)
    
                Catch
                End Try
            End Using
    
            _metaFile.Dispose()
    
            Return bmpOut
        End Function
    
        Private Function DrawRecords(recordType As EmfPlusRecordType, flags As Integer, dataSize As Integer, data As IntPtr, callbackData As PlayRecordCallback) As Boolean
            Dim data_array As Byte() = Nothing
    
            If Not data.Equals(IntPtr.Zero) Then
                data_array = New Byte(dataSize - 1) {}
                Marshal.Copy(data, data_array, 0, dataSize)
            End If
    
            _metaFile.PlayRecord(recordType, flags, dataSize, data_array)
    
            Return True
        End Function
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If _metaFile IsNot Nothing Then
                _metaFile.Dispose()
            End If
        End Sub
    End Class


    Monday, May 11, 2015 1:16 AM
  • Ok, now its working.

    Not trying to be difficult, but we lost the background color?

    Monday, May 11, 2015 1:43 AM
  • what background color? Do you mean the dropshadow?

    Regards,

      Thorsten


    Monday, May 11, 2015 2:01 AM
  • what background color? Do you mean the dropshadow?

    Regards,

      Thorsten



    No, sorry, I mean the yellow color. Here is the form and chart of your last example. Same chart as the others. I moved the button and form size. It doesnt matter.

    I have studied it some more and we are still just printing a bitmap. Right? Although we are redrawing it at a larger size using the metafile.

    So, Here the bmp is set to the size of the form:

        Dim bmp As Bitmap = mtbc.GetBitmapFromMetafile(_stream2, Me.ClientSize.Width, Me.ClientSize.Height)

    I think we need to use the BIG bitmap method now. I added a scalefactor and used the margins size for the bmp we draw the metafile upon. This gives a better printed image that compares to my other BIG bitmap example using a second BIG chart to get the image. Look at the lower left of the curved red line on a printout. The big method smoothes it out. Other things.

    Private Sub PrintDocument1_PrintPage(sender As System.Object, ev As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage PrintDocument1.OriginAtMargins = False Dim mtbc As New MetaFileToBitmapConverter() _stream2.Seek(0, 0) _stream2.Position = 0

    'Dim bmp As Bitmap = mtbc.GetBitmapFromMetafile(_stream2, Me.ClientSize.Width, Me.ClientSize.Height) Dim scalefactor As Single = 5 Dim bmp As Bitmap = mtbc.GetBitmapFromMetafile(_stream2, ev.MarginBounds.Width * scalefactor, ev.MarginBounds.Height * scalefactor) ev.Graphics.DrawImage(bmp, ev.MarginBounds) bmp.Dispose() ev.HasMorePages = False End Sub


    Monday, May 11, 2015 2:57 AM
  • Hi Tommy,

    yes you're right! :-)

    Regards,

      Thorsten

    Monday, May 11, 2015 3:06 AM
  • Two more observations on the metafile method. With the last change it lost the color and the border shading ticks which can be good or bad depending on what you like. Here is a print preview comparison.

    I noticed when printing to Bullzip, a pdf printer, it causes a System.AccessViolationException on playrecord in drawrecords. So, not sure what that is.

    What say you now Jeffery?

    Monday, May 11, 2015 3:59 AM
  • I'll try to read the metafile in an office prog later... using the winapi to copy it to file...
    Monday, May 11, 2015 4:10 AM
  • Hello Tommy,

       First, Thank you for both your helping me with this. I took and put the code in the my application and i had no problems with it. As for printing it using pdf printer, I have adobe acrobat and it prints just fine. Like also Tommy, you are big help me things.

    Just to show you what i was doing to make it print

    Private Sub pd_PrintPage(sender As Object, ev As PrintPageEventArgs)
            'Note, the chart printing code wants to print in pixels.
            Dim marginBounds As Rectangle = ev.MarginBounds
    		
            If Not (ev.Graphics.PageUnit = GraphicsUnit.Pixel) Then
                ev.Graphics.PageUnit = GraphicsUnit.Pixel
    
                'sets the size of the object
               marginBounds.X = CInt(marginBounds.X * (ev.Graphics.DpiX / 100.0F))
                marginBounds.Y = CInt(marginBounds.Y * (ev.Graphics.DpiY / 100.0F))
                marginBounds.Height = CInt(marginBounds.Height * (ev.Graphics.DpiX / 100.0F))
                marginBounds.Width = CInt(marginBounds.Width * (ev.Graphics.DpiY / 100.0F))
            End If
    
            'draws the image as for document
            ev.Graphics.DrawImage(SigmaAid.Drawing.Image.PrintImage(Chart1), marginBounds)
        End Sub
    	
    	 Public Shared Function PrintImage(chart As System.Windows.Forms.DataVisualization.Charting.Chart) As System.Drawing.Image
                'Path and file name for the temp image
                Dim strFileName As String = String.Format("{0}.tmp", Scs.Tools.IO.GenerateGUID) 'Temporary File Name
                Dim path As String = String.Format("{0}\Temp", System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)) 'Path to save File
                Dim fullName As String = System.IO.Path.Combine(path, strFileName) 'Path and file name combined
    
                'Checks to see if the path existed and if not creates it.
                If Not My.Computer.FileSystem.DirectoryExists(path) Then
                    My.Computer.FileSystem.CreateDirectory(path)
                End If
    
                'Save the image file
                chart.SaveImage(fullName, System.Drawing.Imaging.ImageFormat.Emf)
    
                'Loads the emf file into an image object
                Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(fullName)
    
                Return img
            End Function

    As, you can see i was saving the chart at emf file then opening it again then returning as an image.

    Now I have figure out how to copy to clipboard then to any application.

    I have some code form this post https://support.microsoft.com/en-us/kb/323530?wa=wsignin1.0

    Shane

    Monday, May 11, 2015 6:14 AM
  • Jeffery,

    Ok that's good.

    If you want, post the final code you have to make the .emf file you are saving. Are you using the stream as you showed in the first example? It is helpful for me and others from the future looking at this thread.

    Well if you have problems with the clipboard just post another question. 

    Monday, May 11, 2015 1:01 PM
  • Hello tommy,

        I will take and post the final code that i have tomorrow.. and i was able to to get the clipboard working but i need to get working a stream and not saving the file and opening it again..

    With trying to get it work with the clipboard i did notice why the metafile was not working with the stream.. I really is not valid metafile, everything is there, but the format is not correct and i see why you need to use the playrecord method. I will play around with some more and see if get work with the stream..

    Shane

    Thursday, May 14, 2015 1:04 PM
  • Jeffrey and Thorsten,

    I have made a Tech Wiki article about this do you want to participate before I post it?

    If not I will reference both of you and this thread. Unless you don't want me to.

    And you can both edit and add to etc with a Wiki after its posted.

    Thursday, May 14, 2015 11:38 PM
  • Hi Tommy,

    > I will reference both of you and this thread.

    yes, do it (for my person)

    More or less OT:

    I'm currently working on "commenting code" of my small VB program to reshape images (dog-ears, rollup etc) - and commenting is much more hard than writing code for me, so I think, I can look at your article not before its finished and online. [If you like to see: https://onedrive.live.com/redir.aspx?cid=d5e5bd21dbf5e4e9&resid=d5e5bd21dbf5e4e9!3475&parId=d5e5bd21dbf5e4e9!1479&authkey=! but I only commented the dog-ears section and the wave a bit yet...]

    Regards,

      Thorsten


    Thursday, May 14, 2015 11:51 PM
  • Hi Tommy,

    > I will reference both of you and this thread.

    yes, do it (for my person)

    More or less OT:

    I'm currently working on "commenting code" of my small VB program to reshape images (dog-ears, rollup etc) - and commenting is much more hard than writing code for me, so I think, I can look at your article not before its finished and online. [If you like to see: https://onedrive.live.com/redir.aspx?cid=d5e5bd21dbf5e4e9&resid=d5e5bd21dbf5e4e9!3475&parId=d5e5bd21dbf5e4e9!1479&authkey=! but I only commented the dog-ears section and the wave a bit yet...]

    Regards,

      Thorsten


    Ok then I have posted the Wiki article.

    Note that I optimized the code some and I ended up doing away with the class. It has good things but for the example I just used the code that was required and put it in the PrintPage sub. And that turned out to be only about 4 lines to make it all work. The memory stream goes straight to the printer with no intermediate bitmap. It is drawn the exact size of the printout so there is no loss of resolution.

    Friday, May 15, 2015 10:20 PM