Printing a Graphic Object VB.NET - vb.net

I have a module that generates fill out a System.Drawing.Graphics object.
I then try to print it with a event on my main form but the print preview comes out blank.
This is my print page
Private Sub MyPrintDocument_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles MyPrintDocument.PrintPage
Dim MyGraphic As Graphics
MyPrintDocument.PrinterSettings.DefaultPageSettings.Margins.Top = 200
MyPrintDocument.PrinterSettings.DefaultPageSettings.Margins.Left = 100
MyPrintDocument.PrinterSettings.DefaultPageSettings.Margins.Right = 100
MyPrintDocument.PrinterSettings.DefaultPageSettings.Margins.Bottom = 75
MyGraphic = MyGrpahicPage
End Sub
MyGrpahicPage is the public graphics object my module fill out.

I think the problem is that you have to print to the Graphics object provided by the event argument, not another one that you may have hanging around. In other words, you need to draw on e.Graphics. The help page for PrintPageEventArgs.Graphics shows how this is supposed to work.

I found the way.
1. step: you must create thy MyGraphics in your form:
... Form declaration ...
Private GrBitmap As Bitmap
Private GrGraphics As Graphics
Dimm Withevents pd as new PrintDocument 'The withevents is important!
...
2. step: Anywhere (ig, in the formload sub, or in a buttonclick sub) :
GrBitmap = New Bitmap(Width, Height)
GrGraphics = Graphics.FromImage(GrBitmap)
...
(the Width and the Height values you must calculate by the content of the graphics)
3. step:
Complete the GrGraphics with any .DrawString, .DrawLine, etc. methods
4. step:
Create a sub of Printdocument:
Private Sub pd_PrintPage(sender As Object, ev As PrintPageEventArgs) Handles pd.PrintPage
ev.Graphics.DrawImage(Me.GrBitmap, New Point(0, 0))
End Sub

Related

How to Remove a control from another Sub than the one where the control was initially created in VB .NET

I have written some code to create a PictureBox every time the code runs, which works fine.
Public Sub BtnHit_Click(sender As Object, e As EventArgs) Handles BtnHit.Click
Dim PicBoxNewCard As New PictureBox
PicBoxNewCard.Width = 114
PicBoxNewCard.Height = 166
PicBoxNewCard.SizeMode = PictureBoxSizeMode.Zoom
DrawCard(PicBoxNewCard)
Me.Controls.Add(PicBoxNewCard)
PicBoxNewCard.Location = New Point((257 + (57 * DrawnCardCounter)), 349)
But I want to be able to delete these created PictureBoxes by pressing a button, which would be in a different sub to the one that creates the Boxes.
I have googled around and have found references to creating Classes, Panels etc and have not had any success. I have found the exact code that I need to make it work, (Me.Controls.Remove(PicBoxNewCard)) but it only seems to work when executed in the same Sub.
Set the Name or Tag property and use that later when searching for the PictureBox to remove.
PicBoxNewCard.Name = $"Card{DrawnCardCounter}"
Private Sub RemoveButton_Click(sender As Object, e As EventArgs) Handles RemoveButton.Click
RemoveCardPicBox(10)
End Sub
Private Sub RemoveCardPicBox(CardNumber As Integer)
Dim delpicBox As PictureBox = Me.Controls.OfType(Of PictureBox).Where(Function(x) x.Name = $"Card{CardNumber}").FirstOrDefault
If Not delpicBox Is Nothing Then
Me.Controls.Remove(delpicBox)
End If
End Sub

Graphics causing solid white button

I'm coding Conway's game of life. My grid is entirely in a picture box but when I load the form the back button in the upper right is completely white. Refreshing the form fixes the button but makes it incredibly laggy. Every other button shows up fine, just the back button is broken. How can I fix this?
Option Strict On
Public Class frmGame
' Declaring public variables
Public bmp As Bitmap
Public G As Graphics
Public WithEvents speed As Timer
Public grid(50, 40) As Boolean
Public input(50, 40) As Boolean
Public intGens As Integer = 0
Public change As Boolean = False
Public P As New Pen(Color.Black)
Private Sub picGrid_Paint(sender As Object, e As PaintEventArgs) Handles picGrid.Paint
' Loads bitmap, graphics, etc and prepares to begin simulation
' Creates graphics device
bmp = New Bitmap(600, 480)[enter image description here][1]
picGrid.Image = bmp
G = Graphics.FromImage(bmp)
' Defining variables for grid
Dim x As Integer = 0
Dim y As Integer = 0
' Draws grid
For y = 0 To 480
For x = 0 To 600
G.DrawRectangle(pen:=P, x:=x, y:=y, width:=12, height:=12)
x += 12
Next
x = 0
y += 12
Next
End Sub
Private Sub btnBack_Click(sender As Object, e As EventArgs) Handles btnBack.Click
' Hides rules form, shows main menu form
frmMainMenu.Show()
Me.Hide()
End Sub
Private Sub frmGame_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
' Frees memory when form is closed
G.Dispose()
bmp.Dispose()
speed.Dispose()
End Sub
End Class
I'm not exactly sure do I understand your problem, nor I can recreate it with code provided.
But I can recommend some thing's that can help you.
First of all do not use Control.Refresh() while working with drawing, use instead Control.Invalidate() & Control.Update(), that may fix lag issue.
Do you relay need 2 forms (that i understand is the root of problem)?
Instead of hiding form, hide PictureBox (.Visible = False) and show other controls you need at that moment.

How to randomize a picture box within a certain area

So,I am trying to make a game that is based on collecting items to earn points and the objective is to always try and beat your high score. I have make it so the crate randomises at a random position anywhere on the form, I have a background of a city in my form, so I now want it to randomise only on the roads instead of anywhere on the form, I have also created a picture box for each of the roads and had put it into an array,but I don't know if that would be of any use, so i am kinda stuck now. Can anyone help me with this problem?
Thx
This one works but try it first on a seperate program and
after you try it. You will be given a chance on how you will
do the randomize on your own.
Create a program
Add a new form (Form1)
Add a picturebox and a button
Import your moms picture inside the picturebox (Remember : it will not work if you dont do it XD)
Inside your form add this piece of code:
Public Class Form1
Dim RandomClass As New Random()
Dim Y As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
PictureBox1.Show()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For pos = 1 To 100
Y = RandomClass.Next(300)
PictureBox1.Location = New Point(100, Y)
Next pos
End Sub
End Class
The output of that is
The maximum location of the picture of your mother will be at the max of 300 with random location between 0 to 300 just adjust anywhere you want.
Thats all :)

How to use the Paint event more than once on a form?

Okay, so I am trying to make a program that each time you click (doesn't matter where) a random colored, and sized circle appears where you happened to click. however, the only way I can add a shape is via Paint event. here is the code I have now:
Private Sub Form1_Paint(ByVal Sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
Using Brush1 As New SolidBrush(Color.Orange)
e.Graphics.FillEllipse(Brush1, MousePosition.X, MousePosition.Y, 100, 100)
End Using
End Sub
I need to know a line of code that I can use in a mouse click event, that will re-run this sub. I know how to change the size, and make it random, I just don't know how to run this sub multiple times, more precisely; run this sub once after each mouse click. If someone can help, I would appreciate it!
Just as Plutonix explained, a refresh is handled by calling the Invalidate method.
The thing you need to remember is that whatever is painted on a surface is not persistent, so you need to redraw the whole screen every time. There are, of course, many ways in which this can be optimized for performance purposes, as this process can be extremely CPU intensive; specially, since GDI+ is not hardware accelerated.
So, what you need to do is:
Record every click (x, y position) and store it
Since the radius of each circle is random, determine the radius when the user clicks the form, then store it along with the x, y position of the click
Then, have the Paint event re-draw each stored sequence of clicks (with their respective radii) and re-draw each circle over and over.
Here's an implementation that will do the trick. Just paste this code inside any Form's class to test it:
Private Class Circle
Public ReadOnly Property Center As Point
Public ReadOnly Property Radius As Integer
Public Sub New(center As Point, radius As Integer)
Me.Center = center
Me.Radius = radius
End Sub
End Class
Private circles As New List(Of Circle)
Private radiusRandomizer As New Random()
Private Sub FormLoad(sender As Object, e As EventArgs) Handles MyBase.Load
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True) ' Not really necessary in this app...
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.ResizeRedraw, True)
Me.SetStyle(ControlStyles.UserPaint, True)
End Sub
Private Sub FormMouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
circles.Add(New Circle(New Point(e.X, e.Y), radiusRandomizer.Next(10, 100)))
Me.Invalidate()
End Sub
Private Sub FormPaint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim g As Graphics = e.Graphics
g.Clear(Color.Black)
Using p As New Pen(Color.White)
For Each c In circles
g.DrawEllipse(p, c.Center.X - c.Radius \ 2, c.Center.Y - c.Radius \ 2, c.Radius, c.Radius)
Next
End Using
End Sub
Here's what you'll get after a few clicks on the form

how do i print my form?

I need to print an image of my VB.Net Windows.Form when the user clicks a button. Is there a good method for doing this?
You need to use the PrintForm component. Please see How to: Print a Form by Using the PrintForm Component:
The PrintForm component enables you to
quickly print an image of a form
exactly as it appears on screen
without using a PrintDocument
component. The following procedures
show how to print a form to a printer,
to a print preview window, and to an
Encapsulated PostScript file.
If you want to amend the image the following code will capture the bitmap and send it to the printer (On the Button1 Click)
Imports System.Drawing.Printing
Public Class Form1
Dim WithEvents mPrintDocument As New PrintDocument
Dim mPrintBitMap As Bitmap
Private Sub m_PrintDocument_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles mPrintDocument.PrintPage
' Draw the image centered.
Dim lWidth As Integer = e.MarginBounds.X + (e.MarginBounds.Width - mPrintBitMap.Width) \ 2
Dim lHeight As Integer = e.MarginBounds.Y + (e.MarginBounds.Height - mPrintBitMap.Height) \ 2
e.Graphics.DrawImage(mPrintBitMap, lWidth, lheight)
' There's only one page.
e.HasMorePages = False
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
' Copy the form's image into a bitmap.
mPrintBitMap = New Bitmap(Me.Width, Me.Width)
Dim lRect As System.Drawing.Rectangle
lRect.Width = Me.Width
lRect.Height = Me.Width
Me.DrawToBitmap(mPrintBitMap, lRect)
' Make a PrintDocument and print.
mPrintDocument = New PrintDocument
mPrintDocument.Print()
End Sub
End Class
If you really want a snapshot of the form, you'll have to simulate a screen capture. Here's a sample that'll help. It's going to be pretty ugly though, so you may want to consider making it a report using a PDF or report builder.