VB.NET Class method handles paint event - vb.net

How can i use clause Handles in my class method. For example i want to draw an image on picturebox1 with code:
Public Class cell
Public Sub draw_cell() Handles picturebox1.paint
code
End Sub
End Class
I have an error:
Handles clause requires a WithEvents variable defined in the containing type or one of its base types.
How can i do this without using
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
ps. sorry for bad english.

You can create your own routines to draw to your canvas.
Option Strict On
Option Explicit On
Option Infer Off
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim canvas As New Bitmap(PictureBox1.Width, PictureBox1.Height)
Dim canvasGraphics As Graphics = Graphics.FromImage(canvas)
Dim cellRect As New Rectangle(100, 100, 100, 100)
cell.draw(canvasGraphics, cellRect, Color.Red, New Pen(New SolidBrush(Color.Green), 1))
PictureBox1.Image = canvas
End Sub
Public Class cell
Public Shared Sub draw(ByRef canvasGraphics As Graphics, ByVal cellRect As Rectangle, ByVal fillColor As Color, ByVal borderPen As Pen)
Dim renderedCell As New Bitmap(cellRect.Width, cellRect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
Dim borderRect As New Rectangle(0, 0, cellRect.Width - 1, cellRect.Height - 1)
Dim context As BufferedGraphicsContext
Dim bGfx As BufferedGraphics
context = BufferedGraphicsManager.Current
context.MaximumBuffer = New Size(cellRect.Width + 1, cellRect.Height + 1)
bGfx = context.Allocate(Graphics.FromImage(renderedCell), New Rectangle(0, 0, cellRect.Width, cellRect.Height))
Dim g As Graphics = bGfx.Graphics
g.Clear(fillColor)
g.DrawRectangle(borderPen, borderRect)
bGfx.Render()
canvasGraphics.DrawImage(renderedCell, cellRect.Location)
End Sub
End Class
End Class

Related

VB.NET Winforms: Overlay two images and move overlay with timer

I would like to overlay 2 images and then move the top layer using a timer.
this is the code i'm trying to implement from this anwser: here
Imports System.Drawing
Dim OverlayImage As New Bitmap("Some Path", True)
Dim BackImage As New Bitmap("Some Path", True)
g As Graphics = Graphics.FromImage(BackImage)
g.DrawImage(OverlayImage, 0, 0)
pictureBox1.Image = BackImage
If you want to have the timer move the overlayed image, then first, make a variable
Dim posX As Integer = 0
then use
g.DrawImage(OverlayImage, posX, 0)
Now when your timer ticks, increment posX by 10
This is what i got but the overlay isn't moving.
What am i doing wrong? Can anybody help me?
Imports System.Drawing
Public Class Form1
Dim OverlayImage As New Bitmap("D:/white.png", True)
Dim BackImage As New Bitmap("D:/bg.png", True)
Dim g As Graphics = Graphics.FromImage(BackImage)
Dim posX As Integer = 0
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Picturebox1.Image = BackImage
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
g.DrawImage(OverlayImage, posX, 0)
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
posX = +10
End Sub
End Class

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

Managing Dynamically created User Controls events

I have a User Control that is Dynamically created. It has to raise a Mouse_Move event & Mouse_Down event.
How to manage events for Multiple User Control that are created dynamically. I was considering using a list of user controls to track the controls. But I do not know how to setup the events properly.
Public Class UserControl1
Public Structure Porportions
Dim width_Percent As Double
Dim Height_percent As Double
Dim X_Location_Percent As Double
Dim Y_Location_Percent As Double
End Structure
Dim Pipe As Porportions
Dim guage1 As Porportions
Dim guage2 As Porportions
Public start_pos As Point
Public move_offset As Point
Public Client_Point As Point
Public Pipe_Source As Excel
Public Pipe_Data As DataSet
Public Pipe_Properties As Pipe
Private Pipe_ID As String
' Public Event Pipe_MouseMove(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event Pipe_MouseMove1(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event Pipe_MouseDown1(ByVal sender As Object, ByVal e As System.EventArgs)
Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
RaiseEvent Pipe_MouseMove1(sender, e)
End Sub
Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
RaiseEvent Pipe_MouseDown1(sender, e)
End Sub
Public Class Form1
Private pipe_cnt As Integer = 0
Private start_position As Point
Private MoveOffset As Point
Private Mouse_Position As Point
Private WithEvents pp As UserControl1
Private Sub Pipe_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles pp.Pipe_MouseMove1
Dim dx As Integer
Dim dy As Integer
Dim m_loc As Point
Dim scrn As Point
m_loc = New Point(e.Location)
Mouse_Position = New Point(e.X, e.Y)
scrn = PointToScreen(Mouse_Position)
Mouse_Position = PointToClient(Mouse_Position)
dx = start_position.X - Mouse_Position.X
dy = start_position.Y - Mouse_Position.Y
MoveOffset = New Point(dx, dy)
If e.Button = MouseButtons.Left Then
Try
pp.Location = New Point(pp.Left + e.X, pp.Top + e.Y)
pp.Location = New Point(pp.Left + e.X, pp.Top + e.Y)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End If
End Sub
Private Sub Pipe_MouseDown1(ByVal sender As Object, ByVal e As System.EventArgs) Handles pp.Pipe_MouseDown1
start_position = New Point(pp.Location)
End Sub
What I understand that you want to use an same event for multiple user controls. There are many methods to achieve this.
Method 1 (Easiest):
Just put handler events after Handles clause and separate them by commas ,. See example:
Private Sub MouseMove_Event(sender As Object, e As MouseEventArgs) Handles Pipe.MouseMove, PictureBox1.MouseMove
MsgBox("MouseMove")
End Sub
Private Sub Click_Event(sender As Object, e As MouseEventArgs) Handles Pipe.Click, PictureBox1.Click
MsgBox("Click")
End Sub
Private Sub MouseDown_Event(sender As Object, e As MouseEventArgs) Handles Pipe.MouseDown, PictureBox1.MouseDown
MsgBox("MouseDown")
End Sub
Method 2 (burden):
Create and collect all controls in a array of controls and then create events in a foreach loop.
Create Sub that gets array of controls and add handlers using foreach loop.
Private Sub CreateHandlers(Controls() As Control)
For Each control As Control In Controls
Me.Controls.Add(control)
AddHandler control.Click, AddressOf Click_Event
AddHandler control.MouseMove, AddressOf MouseMove_Event
AddHandler control.MouseDown, AddressOf MouseDown_Event
Next
End Sub
Your events
Private Sub Click_Event(sender As Object, e As EventArgs)
'Handle Click events here
End Sub
Private Sub MouseMove_Event(sender As Object, e As EventArgs)
'Handle MouseMove events here
End Sub
Private Sub MouseDown_Event(sender As Object, e As EventArgs)
'Handle MouseDown events here
End Sub
Create controls dynamically and just call CreateHandlers(controls) at end
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim pictureBox1 As PictureBox = New PictureBox _
With {
.Size = New Size(100, 100),
.Location = New Point(0, 0),
.BackColor = Color.Black
}
Dim panel1 As Panel = New Panel _
With {
.Size = New Size(100, 100),
.Location = New Point(100, 0),
.BackColor = Color.Red
}
Dim tableLayoutPanel1 As TableLayoutPanel = New TableLayoutPanel _
With {
.Size = New Size(100, 100),
.Location = New Point(200, 0),
.BackColor = Color.Green
}
Dim controls() As Control = {pictureBox1, panel1, tableLayoutPanel1}
CreateHandlers(controls)
End Sub
End Class

VB.NET paint application

I'm facing two problems in my application:
The Undo Function
The Drawing Part
When i draw on the picturebox , it draws very well, when - let's say I want to undo an action, it undo's it but when I click back on the picturebox it reacts like a redo function ,all the drawings appear back on the image.
the second problem is : i want to be able to edit a picture so i load a image by clicking on a listview item but due to something i'm missing the image it is not show but instead it shows a white background in which i am able to draw.
bellow is the code i am using
Imports Microsoft.VisualBasic.PowerPacks
Public Class Form1
Public drawgraph, g As Graphics
Private redoBuffer As New Stack(Of Image)()
Private undoBuffer As New Stack(Of Image)()
Dim color As Color
Dim UndoStack As New Stack(Of Bitmap)()
Dim xStart, yStart, xEnd, yEnd As Integer
Public Drawbitmap As Bitmap
Dim Drawgraphics As Graphics
Dim myPen As New Pen(color.Black, 4)
Dim myColor As Color = color.Black
Dim myPenWidth As Integer
Dim myBGColor As Color = color.White
Dim Drawing As Boolean
Private Sub drawMyline()
PictureBox4.Image = Drawbitmap
Drawgraphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
Drawgraphics.DrawLine(myPen, xStart, yStart, xEnd, yEnd)
End Sub
Private Sub PushUndo(ByVal b As Bitmap)
UndoStack.Push(b)
End Sub
Private Function PopUndo() As Bitmap
If UndoStack.Count = 0 Then
Return Nothing
Exit Function
End If
If UndoStack.Count > 0 Then
Return UndoStack.Pop
End If
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Drawbitmap = New Bitmap(PictureBox4.Width, PictureBox4.Height)
Drawgraphics = Graphics.FromImage(Drawbitmap)
PictureBox4.Image = Drawbitmap
Drawgraphics.Clear(color.White)
myPenWidth = NumericUpDown1.Value
xStart = -1
yStart = -1
Drawing = False
End Sub
Private Sub PictureBox7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox7.Click
Dim bmp As Bitmap
bmp = PopUndo()
If bmp IsNot Nothing Then
PictureBox4.Image = bmp
End If
End Sub
Private Sub PictureBox4_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox4.MouseDown
Drawing = True
PushUndo(PictureBox4.Image.Clone)
End Sub
Private Sub PictureBox4_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox4.MouseUp
Drawing = False
End Sub
Private Sub PictureBox4_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox4.MouseMove
If Drawing Then
xStart = e.X
yStart = e.Y
drawMyline()
End If
xEnd = e.X
yEnd = e.Y
End Sub
End Class
I tried making changes but i can't load the image i want into the picturebox4 and draw on it , it always loads a white background as for the undo function it works until a click again on picturebox4 and all the undone drawings appear back. Can someone help me fix this 2 problems that I have?

VB.net changing text in onPaint sub

Hey all i have the following code that works just fine when my form loads up:
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
Dim custFont As New PrivateFontCollection()
Dim solidBrush As New SolidBrush(Color.FromArgb(255, 0, 0, 255))
Dim string2 As String = "AntiAlias"
custFont.AddFontFile("C:\aFont.ttf")
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias
e.Graphics.DrawString(string2, New Font(custFont.Families(0), 100, FontStyle.Regular, GraphicsUnit.Pixel), solidBrush, New PointF(10, 60))
End Sub
However, i need a way to update that font text whenever i push a button(s) on the form itself. I tried making a sub like so:
Public Sub changeText(ByVal e As System.Windows.Forms.PaintEventArgs, ByVal theText as string)
Dim custFont As New PrivateFontCollection()
Dim solidBrush As New SolidBrush(Color.FromArgb(255, 0, 0, 255))
custFont.AddFontFile("C:\aFont.ttf")
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias
e.Graphics.DrawString(theText, New Font(custFont.Families(0), 100, FontStyle.Regular, GraphicsUnit.Pixel), solidBrush, New PointF(10, 60))
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
changeText(Me.OnPaint, "just a test")
End Sub
But i end up having an error:
Overload resolution failed because no accessible 'OnPaint' accepts this number of arguments.
on line:
changeText(Me.OnPaint, "just a test")
Any help would be great! Thanks!
Move the string out to class level so you can change it:
Imports System.Drawing.Text
Public Class Form1
Private string2 As String = "AntiAlias"
Private custFont As New PrivateFontCollection()
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
custFont.AddFontFile("C:\aFont.ttf")
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
Using solidBrush As New SolidBrush(Color.FromArgb(255, 0, 0, 255))
Using fnt As New Font(custFont.Families(0), 100, FontStyle.Regular, GraphicsUnit.Pixel)
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias
e.Graphics.DrawString(string2, fnt, solidBrush, New PointF(10, 60))
End Using
End Using
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
string2 = "just a test"
Me.Refresh()
End Sub
End Class