I have a small application that draws pressure vessels. its not much, just drawing rectangles and arcs.
The user provides input and presses a button to generate the drawing.
But if you keep jamming the button, the process memory increases with each button press. How can I avoid this?
Is the image not disposed by placing a new one in to the picture box?
Private Sub btnRedraw_Click(sender As Object, e As EventArgs) Handles btnRedraw.Click
Dim oBlackPen As New Pen(Color.Black, oBitmapHeight / 1000)
If Not pbVessel.Image Is Nothing Then
pbVessel.Image.Dispose()
End If
Dim oImage As Bitmap = New Bitmap(Convert.ToInt16(oBitmapWidth), Convert.ToInt16(oBitmapHeight))
Dim oGraphics As Graphics = Graphics.FromImage(oImage)
' Le fancy drawing code
pbVessel.Image = oImage
End Sub
Edit: I dispose the picturebox image if the image is not nothing, the problem is still persistent.
Related
I'm trying to get familiar with graphics in vb.net and want to draw just a straight line going from the top left to the bottom right of my form Form1 without using the Form1_Paint method but by using Button1
However, the line is only drawn about a quarter of the way and stops as shown in the picture:
I think I need to increase the Clip of the Graphics Object z and I tried the following but it doesn't work. I also tried decreasing the Clip size and that worked as expected.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
z.Clip.MakeInfinite()
z.DrawLine(pen1, 0, 0, Me.Size.Width, Me.Size.Height)
End Sub
pen1 and z are initialized at the start of the program as follows:
Dim z As Graphics = CreateGraphics()
Dim pen1 = New Pen(Color.Black, 3)
I also tried using different set values for the x2 and y2 but nothing managed to be drawn outside of the box apart from using Form1_paint.
It has nothing to do with the clip, and everything to do with WHEN you called CreateGraphics(). At the point that the graphics was created, the form was not fully initialized and it is using the incorrect size.
When you use CreateGraphics() or create a Pen, you should explicitly Dispose() of them as soon as you're done. This is best accomplished via a Using block:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using z As Graphics = CreateGraphics()
Using pen1 = New Pen(Color.Black, 3)
z.DrawLine(pen1, 0, 0, Me.ClientSize.Width, Me.ClientSize.Height)
End Using
End Using
End Sub
In general, though, using CreateGraphics() in this manner is almost always the INCORRECT approach. The line drawn this way is TEMPORARY. Minimize the form and restore it and the line will be gone.
I am displaying images using a timer and picturebox. The images seem to be adding on top of each other instead of displaying one, then removing that one, and loading another.
As the images are displayed, I would like to overlay text on the images.
Here is the code I am using to create images and text
Dim fname As String = (Actually an array in images(jpg) that display with timer)
Dim bm As New Bitmap(fname)
PicBox.Image = bm
findex -= 1 (index of image array)
Dim g As Graphics = PicBox.CreateGraphics
g.DrawImage(bm, 300, 10)
g.DrawString("Kishman Tukus", New Font("Arial", 24, FontStyle.Bold), Brushes.Green, 400, 100)
g.ResetTransform() '
g.Dispose()
I need the images to display in the picturebox one at a time using the timer and I need to overlay
text on the images too.
can someone help me stop the images from adding to the picturebox instead of displaying one at a time?
Or even better, don't use a PictureBox at all, just display images with text overlay?
In any case, i need to stop the memory bleed.
thank you
I think it's important how you load the images. Do you really load each image by filename each time you show it? That's misleading, as you mentioned there is an array. The distinction is you keep references to these images and you are modifying each one. Remember this is a reference type so the original items gets modified. So you end up with text repeatedly being written over itself. The irony is that if you did actually load the image each tick, then you wouldn't actually have this problem :)
I made something along the lines of what you have (I think), where we use Object.Clone to make a copy in memory of each bitmap which you can modify without modifying the original image.
Private images As New List(Of Bitmap)()
Dim findex As Integer = 0
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim bmCopy = DirectCast(images(findex).Clone(), Bitmap)
Using g As Graphics = Graphics.FromImage(bmCopy)
g.DrawString(Guid.NewGuid().ToString(), New Font("Arial", 24, FontStyle.Bold), Brushes.Green, 400, 100)
End Using
PicBox.Image = bmCopy
findex = (findex + 1) Mod images.Count()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
images.Add(My.Resources.Image1)
images.Add(My.Resources.Image2)
Timer1.Interval = 1000
Timer1.Enabled = True
End Sub
There is no memory leak. You can check the memory increase but the GC eventually clears it out.
I would expect to see something more like:
Dim bm As New Bitmap(fname)
Using g As Graphics = Graphics.FromImage(bm)
g.DrawString("Kishman Tukus", New Font("Arial", 24, FontStyle.Bold), Brushes.Green, 400, 100)
End Using
PicBox.Image = bm
I have an image (800x800p) loaded in a PictureBox. It's slightly interactive, clicking somewhere on it will show tooltips or popup windows.
Occasionally, clicking would result in adding of 100x100 px image on the location where it was clicked. That modification needs to be saved onto the main image.
Any ideas as to how to do this?
Draw the new image over your original image.
For example:
Public Class Form1
Private Sub PictureBox1_Click(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseClick
Dim NewIMG As New Bitmap(100, 100)
Graphics.FromImage(NewIMG).Clear(Color.Black) 'just to make my image black since I don't have any image
'You drawing new image here
Graphics.FromImage(PictureBox1.Image).DrawImage(NewIMG, New Point(e.X - 50, e.Y - 50)) 'mouse position - half new image size so that new image center is placed at cursor location
PictureBox1.Refresh() 'to make picbox redraw and display new image
End Sub
End Class
I'm wanting to show the dragged control while dragging in my form. I have a list of controls (textboxes and a picturebox) which are draggable. I would like to show the dragged control all the time, as long as the control is being dragged, even if the user cannot drop it. I also have an issue with dragging the picture box. It shows a dragged image of the control, however it flickers.
Code for drag feedback for picture box
Private Sub qrCode_GiveFeedback(ByVal sender As Object, ByVal e As GiveFeedbackEventArgs) Handles QRCodeDrag.GiveFeedback
Dim bitmap As Bitmap
bitmap = New Bitmap(QRCodeDrag.Width, QRCodeDrag.Height)
QRCodeDrag.DrawToBitmap(bitmap, New Rectangle(Point.Empty, bitmap.Size))
'bitmap.MakeTransparent(Color.White)
Dim cursor As New Cursor(bitmap.GetHicon)
Cursor.Current = cursor
End Sub
Any ideas?
I forgot to add
e.UseDefaultCursors = False
This solved the issue of the flicker
I'm having a problem when it comes to images with white background. How can I remove the white background or make the image transparent?
For now I'm using this code
Dim _ms3 As New System.IO.MemoryStream()
pbSignCapture.Image.Save(_ms3, System.Drawing.Imaging.ImageFormat.Png)
Dim _arrImage3() As Byte = _ms3.GetBuffer()
_ms3.Close()
Also saving the image using the _arrImage3.
I want to convert the image in the PictureBox to turn the White Background into transparent.
Consider using the Bitmap class to open your image files.
Dim myImage as new Bitmap("C:\Image file.bmp")
And then you can use the MakeTransparent() or MakeTransparent(Color) methods:
Get the color of a background pixel.
Dim backColor As Color = myImage.GetPixel(1, 1)
Make backColor transparent for myBitmap.
myImage.MakeTransparent(backColor)
EDIT:
As I understand from the new details you want to have a PictureBox to be transparent where the source image is transparent. Unfortunately this is not possible using WinForms because the transparency system is not cascading. You can set the BackgroundColorproperty of pictureBox to transparent, but this is going to act differently from what you may think. The free pixels of the PictureBox control will show the content of the parent control.
It means that if you have, for example, a label below your picurebox and set transparent background to the image; the label won't be shown because it is not theparent control of the picturebox.
A workaround is to manually draw the image in the paint event of the destination control.
Let's assume that you have a form with many controls and you want to draw ad image over a button (named btn). You'll have to override the form's paint event this way:
Private Sub form_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles form.Paint
Dim g As Graphics = e.Graphics
g.DrawImage(Image.FromFile("C:/yourimage.png", btn.Location.X, btn.Location.Y)
End Sub