.Net 4.7.2. Winforms.
Rendering a complex page full of text and graphics. I used a Bitmap. I then show it in a preview window by sizing a PictureBox and placing the picturebox into a panel that scrolls.
It works perfectly to a Bitmap, except of course for the 2GB of RAM it takes. So now I'm trying to go to a MetaFile to save RAM and hopefully make something scalable. However when I do this the preview code blows up with "Parameter is not valid" on Width.GET. This happens on ShowDialog for the Preview window.
I verified that the Metafile was not accidentally disposed. It's still there and passed into the preview window as a byref parameter.
Here is the code:
' In the button event handler to create the file
Dim gr As Graphics = Me.CreateGraphics()
Dim hdc As IntPtr = gr.GetHdc()
' [snip irrelevant code]
Try
' [snip irrelevant code]
' [pagewidth and pageheight are paper size in inches * DPI chosen = pixels]
_pedWMF = New Metafile(hdc,
New Rectangle(0, 0, pageWidth, pageHeight),
MetafileFrameUnit.Pixel)
_PedigreeCanvas = Graphics.FromImage(_pedWMF)
_PedigreeCanvas.PageUnit = GraphicsUnit.Pixel
' [snip irrelevant code]
' Text and images rendered in this call
RenderPedigree(PedigreeCanvas)
' [snip irrelevant code]
' Call to preview window to show dialog.
Here is the code in the Preview...
Private Sub LayoutPreviewImage()
_iPageWidth = Convert.ToInt32(Me.DeviceDpi * (Convert.ToDouble(_drvPaperSize("PS_WIDTH")) / 100))
_iPageHeight = Convert.ToInt32(Me.DeviceDpi * (Convert.ToDouble(_drvPaperSize("PS_HEIGHT")) / 100))
SuspendLayout()
Dim p As New PictureBox()
p.Name = "pbPreview"
p.Width = _iPageWidth
p.Height = _iPageHeight
'*** The _wmfPreview variable is properly initialized with the Metafile created above.
If _wmfPreview IsNot Nothing Then p.Image = _wmfPreview
p.SizeMode = PictureBoxSizeMode.Zoom
pPagePreview.Controls.Add(p)
pPagePreview.Location = New Point(0, 0)
pPagePreview.Width = _iPageWidth + Convert.ToInt32(Math.Round(DeviceDpi * 0.5))
pPagePreview.Height = _iPageHeight + Convert.ToInt32(Math.Round(DeviceDpi * 0.5))
p.Left = Convert.ToInt32(Math.Round(DeviceDpi * 0.25))
p.Top = Convert.ToInt32(Math.Round(DeviceDpi * 0.25))
p.BackColor = Color.White
ResumeLayout()
End Sub
Then when I showDialog(), I get the exception.
If I look in the debugger, the MetaFile throws exceptions for width and height and numerous other properties. I know I have something woefully improperly coded, but I cannot figure out what. I used to easily do this with Delphi back in the day. I am missing something; please help me to find it.
Thanks for any help.
OK, the answer was found. Not in the MS Documentation but in a different Stack Overflow answer.
Whenever you finish working on a Graphics object to draw into a Metafile, you then need to Flush and or Dispose the Graphics object to commit those changes into the MetaFile. Like so:
RenderPedigree(PedigreeCanvas, PedigreeCanvas)
PedigreeCanvas.Flush()
PedigreeCanvas.Dispose()
PedigreeCanvas = Nothing
That will do the trick.