PictureBox MouseEnter / MouseLeave Events not Firing - vb.net

Create a new form with three picture boxes. This code is intended to draw a border when the mouse enters the picture box and remove it when it leaves. It is inconsistent in the results. Sometimes it draws/removes the border, sometimes it doesn't. This code is not complex. Using VS 2012.
Private Sub PictureBox_MouseEnter(sender As Object, e As EventArgs) _
Handles PictureBox1.MouseEnter, PictureBox2.MouseEnter, PictureBox3.MouseEnter
Dim pb As PictureBox = DirectCast(sender, PictureBox)
pb.BorderStyle = BorderStyle.FixedSingle
' Debug.WriteLine("E " & pb.Name)
End Sub
Private Sub PictureBox_MouseLeave(sender As Object, e As EventArgs) _
Handles PictureBox1.MouseLeave, PictureBox2.MouseLeave, PictureBox3.MouseLeave
Dim pb As PictureBox = DirectCast(sender, PictureBox)
pb.BorderStyle = BorderStyle.None
' Debug.WriteLine("X " & pb.Name)
End Sub

I could also reproduce the issue. So, expanding on the comments above about "drawing something else" instead of using the Picturebox's property, let me suggest this quick and dirty approach:
Use a RectangleShape object, the one provided by the VisualBasic Powerpack 3.0 addon. Simply put one of those in the same form your PictureBox is in, and make it invisible (visible = false).
The code is also easy:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.RectangleShape1.Location = New Point(Me.PictureBox1.Left - 1, Me.PictureBox1.Top - 1)
Me.RectangleShape1.Size = New Size(Me.PictureBox1.Width + 1, Me.PictureBox1.Height + 1)
End Sub
Private Sub PictureBox1_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.MouseEnter
Me.RectangleShape1.Visible = True
End Sub
Private Sub PictureBox1_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.MouseLeave
Me.RectangleShape1.Visible = False
End Sub
End Class

Need some help from your Form MouseEnter Event ..
Dim pb As PictureBox = New PictureBox
Private Sub Form1_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseEnter
pb.BorderStyle = BorderStyle.None
End Sub
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
pb = PictureBox1
pb.BorderStyle = BorderStyle.FixedSingle
End Sub

I followed KalaNag idea by putting my picturebox inside a panel and handled the event on the pciturebox by doing like this
private void PictureBox_MouseEnter(object sender, EventArgs e)
{
PictureBox control = sender as PictureBox;
(control.Parent as Panel).Width = 20;
(control.Parent as Panel).Height = 20;
(control.Parent as Panel).BorderStyle = BorderStyle.Fixed3D;
}
private void PictureBox_MouseLeave(object sender, EventArgs e)
{
PictureBox control = sender as PictureBox;
(control.Parent as Panel).Width = 18;
(control.Parent as Panel).Height = 18;
(control.Parent as Panel).BorderStyle = BorderStyle.None;
}
I changed the control's size because otherwise, the picturebox keeps flickering when the mouse hovers the borders as the cursor is entering and leaving indefinitely since the borders change the size of the control.
Works like a charm !

Related

Moving a bitmap to the front

So
I need to put an image on a picturebox
I have a form with a panel which contain a picturebox and an image.
I use image because I need to rotate it.
what I get is that the picture cover the image and I need the opposite.
picturebox.sendToBack doesnt work and i cant find img.bringToTop function.
Imports System.Drawing.Drawing2D
Public Class Form1
Dim g As Graphics
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
g = Panel1.CreateGraphics
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim img As Image
img = Bitmap.FromFile(Application.StartupPath & "/pic/" & "clay.jpg")
g.RotateTransform(330)
g.DrawImage(img, 70, 170, 100, 100)
Pb.SendToBack()
End Sub
End Class
[ pictures][1]
https://i.stack.imgur.com/s9goC.jpg
Here is an example of what I linked to in the comments that applies to your specific scenario. This code will draw the same Image on a Panel and a PictureBox. It will work whether the PictureBox is a child of the Panel or a sibling.
Private ReadOnly img As Image = Image.FromFile("file path here")
Private Sub DrawImage(c As Control, g As Graphics)
'The image will be drawn at (100,100) in form coordinates.
'Translate that location to coordinates for the current control.
Dim imgLocation = c.PointToClient(Me.PointToScreen(New Point(100, 100)))
g.DrawImage(img, imgLocation)
End Sub
Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
DrawImage(Panel1, e.Graphics)
End Sub
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
DrawImage(PictureBox1, e.Graphics)
End Sub
In that code, there is an individual Paint event handler for each control and they both call a common method that does the drawing. If you want to, you can bundle it all into a single common event handler:
Private ReadOnly img As Image = Image.FromFile("file path here")
Private Sub Controls_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint,
PictureBox1.Paint
'The image will be drawn at (100,100) in form coordinates.
'Translate that location to coordinates for the current control.
Dim imgLocation = DirectCast(sender, Control).PointToClient(Me.PointToScreen(New Point(100, 100)))
e.Graphics.DrawImage(img, imgLocation)
End Sub

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

Display text for drag and drop images VB.NET

I am developing a simple SQL generator for images. I am having issues getting texts to be displayed in a textbox when I drag pictures into a PictureBox. Am I doing anything wrong? I want a situation when I drag the image into the PictureBox, the textbox shown in blue should display: 'SELECT FROM EMPLOYEE;'. I need help to get this code working. My code is displayed below.
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'' picDropTarget.AllowDrop = True
picAccept.AllowDrop = True
End Sub
Private Sub picSELECT_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picSELECT.MouseDown, picEMPLOYEE.MouseDown
' Start the drag if it's the left mouse button.
If (e.Button = MouseButtons.Left) Then
Dim source As PictureBox = DirectCast(sender, PictureBox)
picSELECT.DoDragDrop(source.Image, DragDropEffects.Copy)
'Added this line to show
'txtSQL.Text = "SELECT"
End If
End Sub
Private Sub picAccept_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles picAccept.DragEnter
' See if this is a copy and the data includes an image.
If (e.Data.GetDataPresent(DataFormats.Bitmap) AndAlso
(e.AllowedEffect And DragDropEffects.Copy) <> 0) _
Then
' Allow this.
'e.Effect = DragDropEffects.All
e.Effect = DragDropEffects.All
Else
' Don't allow any other drop.
' e.Effect = DragDropEffects.None
e.Effect = DragDropEffects.Copy
End If
End Sub
Private Sub picAccept_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles picAccept.DragDrop, picSELECT.DragDrop, picEMPLOYEE.DragDrop
Dim bm As Bitmap = DirectCast(e.Data.GetData(DataFormats.Bitmap, True), Bitmap)
picAccept.Image = bm
End SubEnd Class
TextBox1.Text = "select from EMPLOYEES"
Here's a fully working minimal sample. You can copy/paste the below, drop a file into the PictureBox at the bottom of the form, and the TextBox at the top will get populated with text.
Public Class Form1
Dim txtbx As New TextBox
Dim pctbx As New PictureBox
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
txtbx.Dock = DockStyle.Top
pctbx.Dock = DockStyle.Bottom
pctbx.BackColor = Color.AntiqueWhite
pctbx.AllowDrop = True
Controls.Add(txtbx)
Controls.Add(pctbx)
AddHandler pctbx.DragEnter, AddressOf pctbx_DragEnter
AddHandler pctbx.DragDrop, AddressOf pctbx_DragDrop
End Sub
Private Sub pctbx_DragEnter(sender As Object, e As DragEventArgs)
e.Effect = DragDropEffects.All
End Sub
Private Sub pctbx_DragDrop(sender As Object, e As DragEventArgs)
txtbx.Text = "select from employees where id = "
End Sub
End Class

Creating New Form Controls in Visual Basic

I am trying to have a button, when clicked, creates a new picturebox control. So that everytime I click it, it adds another new picturebox control. These pictureboxes will all have the same functions like being able to move them around and draw on them. But the button only makes one and no more after that with the following code. What am I missing?
Public Class Form1
Dim xpos As New Integer
Dim ypos As New Integer
Dim pos As New Point
Dim x As Integer
Dim y As Integer
Dim canvas As New PictureBox
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim i As Integer = 0
i = i + 1
canvas.Name = "canvas" & i
canvas.BackColor = Color.White
canvas.BorderStyle = BorderStyle.FixedSingle
canvas.Image = Nothing
canvas.Height = TextBox1.Text
canvas.Width = TextBox2.Text
AddHandler canvas.MouseDown, AddressOf PictureBox1_MouseDown
AddHandler canvas.MouseMove, AddressOf PictureBox1_MouseMove
Controls.Add(canvas)
End Sub
Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
xpos = Cursor.Position.X - canvas.Location.X
ypos = Cursor.Position.Y - canvas.Location.Y
End Sub
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
pos = MousePosition
pos.X = pos.X - xpos
pos.Y = pos.Y - ypos
canvas.Location = pos
End If
End Sub
Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
End Class
Dim canvas As New PictureBox
You have multiple bugs in your code but this is the most serious one. The As New syntax ensures that you'll always create a PictureBox object, but it will only ever be one object. And of course, one variable cannot keep track of multiple picture boxes.
What you need to do is create a new one ever time the button is clicked. It is generally a good idea to keep track of the picture boxes you create. So correct code looks like:
Dim canvases As New List(Of PictureBox)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim canvas = New PictureBox
canvases.Add(canvas)
canvas.Name = "canvas" & canvases.Count.ToString()
'' etc...
End Sub
Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
Dim canvas = DirectCast(sender, PictureBox)
xpos = Cursor.Position.X - canvas.Location.X
ypos = Cursor.Position.Y - canvas.Location.Y
End Sub
Note how the sender argument gives you a reference back to the picture box object that's being moused. Do the same thing in any other event handlers.
Increasing the counter whenever a new canvas is created:
Public Class Form1
Dim counter As New Integer
...
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
counter += 1
canvas.Name = "canvas" & counter.ToString()
...
Accessing the canvas that the mouse is currently moving over:
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
pos = MousePosition
pos.X = pos.X - xpos
pos.Y = pos.Y - ypos
DirectCast(sender, PictureBox).Location = pos
End If
End Sub

Put controls on a form border in vb.net?

I have a project where I want to put controls on the form's border, when the formborderstyle is set to formborderstyle.sizable
Formborderstyle.none will not work, since it can't be sized on runtime, and goes in front of the taskbar when maximized.
I'm using vb.net 2010.
I'm not sure if you can override the drawing of the border and if you could not sure how you would add control to the border.
You can temporarily change the border style before you maximize the form.
And you can overload the client event to handle re-sizing the form yourself.
Are there any other reasons you dont want to go with Formborderstyle.none?
Public Class Form1
Inherits Windows.Forms.Form
Private Const BorderWidth As Integer = 30 'This is just for demo purposes.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Panel1.Location = New Point(Me.Width - BorderWidth, 0)
Panel1.Width = BorderWidth
End Sub
Public xLocation, yLocation As Integer
Private Sub Panel1_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown
xLocation = PointToScreen(Cursor.Position).X
yLocation = PointToScreen(Cursor.Position).Y
End Sub
Private Sub Panel1_MouseUp(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseUp
'Stop resizing form
Me.Width = Me.Width + (PointToScreen(Cursor.Position).X - xLocation)
xLocation = PointToScreen(Cursor.Position).X
yLocation = PointToScreen(Cursor.Position).Y
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Sizable
Me.WindowState = FormWindowState.Maximized
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
End Sub
End Class