Why is a painted dot disappears sometime? - vb.net

I try to paint a dot on an image
…
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PictureBox1.Image = Image.FromFile("C:\Users\SHEMMY-7X64\Pictures\postage.jpg")
Using p As New System.Drawing.Pen(Color.Yellow, 4)
Using g As Graphics = PictureBox1.CreateGraphics()
g.DrawEllipse(p, 15, 5, 10, 10)
End Using
End Using
End Sub
The image is painted but not the dot.
When separating the code to 2 steps:
1. Load the image
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PictureBox1.Image = Image.FromFile("C:\Users\SHEMMY-7X64\Pictures\postage.jpg")
End Sub
2. paint
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Using p As New System.Drawing.Pen(Color.Yellow, 4)
Using g As Graphics = PictureBox1.CreateGraphics()
g.DrawEllipse(p, 15, 5, 10, 10)
End Using
End Using
End Sub
This time the dot was painted.
I posted this question at an another site and was told it's a question of timing.
Ok it's a question of timing, but how to solve it?

You need to draw everything including the image. You could:
Create a class level variable of Bitmap type and name it say, Bmp:
Private Bmp as Bitmap
To load a new image:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'dispose the old image if any:
bmp?.Dispose()
'and assing the new one:
bmp = New Bitmap(Image.FromFile("C:\Users\SHEMMY-7X64\Pictures\postage.jpg"))
'and call:
PictureBox1.Invalidate()
End Sub
Now the painting routine:
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
If bmp IsNot Nothing Then
Dim srcRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
Dim desRect As New Rectangle(0, 0, PictureBox1.Width, PictureBox1.Height)
Dim G As Graphics = e.Graphics
G.SmoothingMode = SmoothingMode.AntiAlias
G.Clear(BackColor) 'or: G.Clear(Parent.Backcolor) if you want.
G.DrawImage(bmp, desRect, srcRect, GraphicsUnit.Pixel)
Using pn As New Pen(Color.Yellow, 4)
G.DrawEllipse(pn, 15, 5, 10, 10)
End Using
End If
End Sub
Finally, don't forget to clean up:
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
bmp?.Dispose()
End Sub
Good luck.

Related

Unwanted cursor flicker when cursor moves inside regions

The following code example paints three rectangles and changes the cursor type to hand/default if the mouse is inside/outside the rectangular regions respectively. The program executes as intended with one exception: when located inside a region, the mouse flickers while being moved.
Having investigated, it seems the issue may relate to a contradiction between my code and an underlying control, with respect to which mouse type to display, resulting in flicker. Whether correct or not, unfortunately I've been unable to resolve the issue. Please can you help?
Imports System.Drawing.Drawing2D
Public Class Form1
Private myRectangles() As Rectangle
Private myRegions(2) As Region
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Write an array of rectangles.
myRectangles = {New Rectangle(100, 100, 50, 50), New Rectangle(200, 200, 50, 50), New Rectangle(300, 300, 50, 50)}
' Write an array of rectangle regions.
For i As Integer = 0 To myRegions.length - 1
Dim myPath As New GraphicsPath
myPath.AddRectangle(myRectangles(i))
Dim myRegion As New Region(myPath)
myRegions(i) = myRegion
Next
End Sub
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
' Iterate myRegions to check if the mouse is over a region.
For i As Integer = 0 To myRegions.Count - 1
Dim IsHit As Boolean = myRegions(i).IsVisible(e.Location)
If IsHit Then
Cursor.Current = Cursors.Hand
Exit For
Else
Cursor.Current = Cursors.Default
End If
Next
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
' Paint myRectangles.
For i As Integer = 0 To myRegions.Length - 1
e.Graphics.DrawRectangle(New Pen(Color.Black, 1), myRectangles(i))
Next
End Sub
End Class
EDIT1: The above MouseMove Sub can be simplified to the following:
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
' Check if the mouse is located within any region.
Dim isHit As Boolean = myRegions.Any(Function(p) p.IsVisible(e.Location))
If isHit Then
Cursor.Current = Cursors.Hand
Else
Cursor.Current = Cursors.Default
End If
End Sub
EDIT2: Revised complete code:
Imports System.Drawing.Drawing2D
Public Class Form1
Private myRectangles() As Rectangle
Private myGraphicsPaths As New List(Of GraphicsPath)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Write a graphics path list of rectangles.
myRectangles = {New Rectangle(100, 100, 50, 50), New Rectangle(200, 200, 50, 50), New Rectangle(300, 300, 50, 50)}
For i As Integer = 0 To myRectangles.Length - 1
Dim myPath As New GraphicsPath
myPath.AddRectangle(myRectangles(i))
myGraphicsPaths.Add(myPath)
Next
End Sub
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
' Check if the mouse is located within any graphicspath.
Dim isHit As Boolean = myGraphicsPaths.Any(Function(p) p.IsVisible(e.Location))
If isHit And Cursor.Current IsNot Cursors.Hand Then
Cursor.Current = Cursors.Hand
Else
Cursor.Current = Cursors.Default
End If
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
' Paint myRectangles.
For i As Integer = 0 To myRectangles.Length - 1
e.Graphics.DrawRectangle(New Pen(Color.Black, 1), myRectangles(i))
Next
End Sub
End Class

Drawing event draws two object

Program has only this code.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PictureBox1.Image = PictureBox2.Image
Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
g.DrawEllipse(New Pen(Color.MediumOrchid, 5), 30, 30, 30, 30)
g.Dispose()
PictureBox1.Refresh()
PictureBox2.Refresh()
End Sub
Before clicking PictureBox1 is emtpty and PictureBox2has a white image.
After clicked PictureBox1 and PictureBox2 both have ellipse.
I think program uses one image for two pictureBox'es.So when I paint they are both painted.I want to set picbox2 white image and picbox1 white image with ellipse.Any solution ?
You have to make a copy of the image, so you will use the same data, but not the same object, and so are safe from changes on the original object.
I am not a vb.net expert, but you may try this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles
Button1.Click
PictureBox1.Image = New Bitmap(PictureBox2.Image)
Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
g.DrawEllipse(New Pen(Color.MediumOrchid, 5), 30, 30, 30, 30)
g.Dispose()
PictureBox1.Refresh()
PictureBox2.Refresh()
End Sub

Which method to use for flicker free images in vb.net in a closed enviroment?

I'm having trouble locating a method for drawing multiple (10-20) images (alpha'd PNG's) onto a form in vb.net without huge flicker.
The main problem is i'm in an closed environment - I can't install any SDKs (so no DirectX) or redist's (so no XNA)
My first thought was GDI+ but I cant find a way that doesn't flicker. A friend recommended SDL using a SDL to C# wrapper, though I'm having trouble as all the c++ tutorials and for speed I'd like to keep the inbuilt winforms functionality if I'm honest.
Is anyone able to suggest a better solution?
Edit: Here's my basic code. It flickers whenever its repainted (i.e. the mouse moves onto or off the form background such as over another control on the form) or when I was using the commented-out timer control (even with a 1s refresh) instead of the onpaint event
Public Class Form1
Dim sprite As Image = Image.FromFile("C:\test\1.png")
Dim background As Image = Image.FromFile("C:\test\2.png")
Dim x As Integer = 20
Dim gfx As Graphics
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
gfx.DrawImage(background, 0, 0, background.Width, background.Height)
gfx.DrawImage(sprite, x + 50, x + 50, sprite.Width, sprite.Height)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
x = x + 10
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
gfx = Me.CreateGraphics
End Sub
'Private Sub smoothPainter_Tick(sender As Object, e As EventArgs) Handles smoothPainter.Tick
' gfx.DrawImage(background, 0, 0, background.Width, background.Height)
' gfx.DrawImage(sprite, x + 50, x + 50, sprite.Width, sprite.Height)
'End Sub
End Class
Don't create a static graphics object. Use the graphics object provided by the PaintEventArgs variable.
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
e.Graphics.DrawImage(background, 0, 0, background.Width, background.Height)
e.Graphics.DrawImage(sprite, x + 50, x + 50, sprite.Width, sprite.Height)
End Sub
Also enable double buffering on the form
Private Sub Form1_Load(sender as Object, e as EventArgs) Handles Me.Load
Me.DoubleBuffered = True
End Sub
You would also probably need to refresh the form after the button click
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
x = x + 10
Me.Invalidate() 'Or Me.Refresh if you want to force an instant redraw
End Sub
It's also often faster/better to draw on an image first and then draw the image onto the form (basically that's what a Double Buffer does).
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Using Bmp as New Bitmap(Me.Width, Me.Height)
Using g as Graphics = Graphics.FromImage(Bmp)
g.DrawImage(background, 0, 0, background.Width, background.Height)
g.DrawImage(sprite, x + 50, x + 50, sprite.Width, sprite.Height)
End Using
e.Graphics.DrawImageUnscaled(b, 0, 0)
End Using
End Sub

VB .NET WinFormApplication Printing Failed Landscape mode after setting

I am using VB .NET programming and I would like to print my WinFormsApplication in landscape mode as the portrait mode could not fit it properly.
I have set the landscape mode as true. You may refer to the code below:
Private Sub PrintAll_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Handles PrintAll.Click
PrintForm1.Form = Me
PrintDocument1.DefaultPageSettings.Landscape = True
PrintForm1.Print(Me, PowerPacks.Printing.PrintForm.PrintOption.FullWindow)
PrintDialog1.ShowDialog()
End Sub
And the result is shown as below in the screenshot
http://s335.photobucket.com/user/blakeex/media/notcomplete.png.html
Could anyone share some hint or guides?
to print the complete client area of a scrollable form, even if the form has been resized.
Try PrintForm1.Print(Me, PowerPacks.Printing.PrintForm.PrintOption.Scrollable)
Here's another way that will print whatever part of the form is viewable on the screen:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
CaptureScreen()
PrintDocument1.DefaultPageSettings.Landscape = True
PrintDocument1.DefaultPageSettings.Margins = New Printing.Margins(0, 0, 0, 0)
PrintDocument1.Print()
End Sub
Dim memoryImage As Bitmap
Private Sub CaptureScreen()
Dim myGraphics As Graphics = Me.CreateGraphics()
Dim s As Size = Me.Size
memoryImage = New Bitmap(s.Width, s.Height, myGraphics)
Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage)
memoryGraphics.CopyFromScreen(Me.Location.X, Me.Location.Y, 0, 0, s)
End Sub
Private Sub printDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim pagerec As New RectangleF(e.PageSettings.PrintableArea.X, e.PageSettings.PrintableArea.Y, e.PageSettings.PrintableArea.Height, e.PageSettings.PrintableArea.Width)
e.Graphics.DrawImage(memoryImage, pagerec, New Rectangle(Me.Location, Me.Size), GraphicsUnit.Pixel)
End Sub

Draw graphics on screen

I am using Visual Basic.Net and am drawing graphics on the screen.
Here is my code:
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
Dim gr As Graphics = Graphics.FromHwnd(New IntPtr(0))
gr.DrawString("text on screen",
New Font(Me.Font.FontFamily, 25,
FontStyle.Regular), Brushes.Red, 50, 50)
End Sub
In the above code, text is drawn on the screen. My question is this: How can I remove the text that is drawn to screen? I see that there is a .Clear method, however, this 'Clears the entire drawing surface and fills it with the specified background color', rather than just removing the drawn text.
Thanks in advance.
EDIT
I am wanting to develop a subliminal message application that will show messages on screen while the user is using other applications. Would the transparent form be the best way to do this?
I have found the following code that works:
Private WithEvents TextForm As New Form
Private Zipper As New FontFamily("Zipper")
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
With TextForm
.BackColor = Color.DimGray
.TransparencyKey = Color.DimGray
.FormBorderStyle = Windows.Forms.FormBorderStyle.None
.ShowInTaskbar = False
.WindowState = FormWindowState.Maximized
.Opacity = 0
.Show(Me)
End With
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Static showText As Boolean
showText = Not showText
If showText Then TextForm.Opacity = 0.99 Else TextForm.Opacity = 0
End Sub
Private Sub TextForm_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles TextForm.Paint
e.Graphics.DrawString("text on screen 12345", New Font(Zipper, 30, FontStyle.Bold), Brushes.Red, 50, 50)
End Sub
Take different bitmaps and draw each new thing in separate bitmaps and after merge new bitmap with old one. When you want to remove text reload old bitmap which is without text.
Search for drawing in new bitmaps and save drawing.
You can try this:
Dim Graphics0 as Graphics = Graphics.fromHwnd(0) 'This is the desktop's graphics
Graphics0.DrawText("Test 1..2..3..",New Font(Arial,10),Brushes.Black,New Point(0,0))