Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Make an image follow the mouse

Status
Not open for further replies.

no1biscuit

Programmer
Oct 8, 2001
67
US
I have a picturebox that I am trying to drop another picturebox on top of it to cover up sections. Basically like a keymap (You are here) thing. But I want to be able to move the mouse around I want the image to follow cursor to help locate it. Here is my function which doesn't work right. It drops and image where my mouse is then I have to move outside the picturebox and then back in to have it move the floating image. Hopefully this make sense. Here is my code for reference. I documented it as best as I could. (Still vb.net newbie)


Thanks for any insight you have
Thom



Private Sub pctlocator_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pctlocator.MouseMove
On Error GoTo Errorhandler
'c is used to find the existing picturebox
Dim c As PictureBox
'ignore
If insertlocatoricon = True Then
'go out and find the existing little image and delete it
'will cause an error number 9 the first time because it
'does not exist
c = Me.Controls.Find("templocator", True)(0)
Me.Controls.Remove(c)

Dim LocalMousePosition As Point
Dim strx As String
Dim stry As String
Dim locatorid As Integer
Dim sizexy As Integer
LocalMousePosition = Cursor.Position

'Where the XY coords are for little image locator
strx = MousePosition.X
stry = MousePosition.Y

'Currently hard coded 20px x 20px red box image
'that is to be dropped on to the keymap
strlocatorname = "C:\Images\locatoricon\2020.jpg"

Dim pic As PictureBox
Dim cm As New ContextMenuStrip

pic = New PictureBox
Me.SuspendLayout()
strimage = strlocatorname
sizexy = 20
pic.Size = New System.Drawing.Size(sizexy, sizexy)
'for some reason I have to subtract a little to get it to place
'on the map where my cursor is at. If not it puts the little
'image too low on the screen
pic.Location = New System.Drawing.Point(strx - 20, stry - 40)
pic.Image = Image.FromFile(strimage)
pic.Name = "templocator"

'want a right click on the image to delete it in the future
AddHandler cm.Click, AddressOf Me.DeleteClick
cm.Items.Add("Delete " & pic.Name, Nothing, New System.EventHandler(AddressOf DeleteLocatorClick))
Me.Controls.Add(pic)
Me.ResumeLayout()
Me.BringToFront()
End If

Exit Sub
Errorhandler:
If Err.Number = 9 Then
Resume Next
Else
MsgBox("Mouse Move error not captured.")
End If



End Sub
 
May be something like this?

Code:
	Private pb2MouseDown As Boolean = False
	Private pb2StartPosition As Point = Nothing

	Private Sub PictureBox2_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseClick

		If e.Button = Windows.Forms.MouseButtons.Right Then
			PictureBox2.Image = Nothing
			PictureBox2.Location = pb2StartPosition
		End If

	End Sub

	Private Sub PictureBox2_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseDown

		pb2MouseDown = True
		If pb2StartPosition = Nothing Then pb2StartPosition = PictureBox2.Location

	End Sub

	Private Sub PictureBox2_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseMove

		If pb2MouseDown Then
			PictureBox2.Location = New Point(PictureBox2.Left + e.Location.X, PictureBox2.Top + e.Location.Y)
		End If

	End Sub

	Private Sub PictureBox2_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseUp

		pb2MouseDown = False

	End Sub
 
A slight modification - this keeps the cursor in the same place relative to the location of the PictureBox that is being moved.

Code:
	Private pb2MouseDown As Boolean = False
	Private pb2StartPosition As Point = Nothing
	Private pb2MouseOffset As Point = Nothing

	Private Sub PictureBox2_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseClick

		If e.Button = Windows.Forms.MouseButtons.Right Then
			PictureBox2.Image = Nothing
			PictureBox2.Location = pb2StartPosition
		End If

	End Sub

	Private Sub PictureBox2_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseDown

		pb2MouseDown = True
		If pb2StartPosition = Nothing Then
			pb2StartPosition = PictureBox2.Location
			pb2MouseOffset = e.Location
		End If

	End Sub

	Private Sub PictureBox2_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseMove

		If pb2MouseDown Then
			PictureBox2.Location = New Point(PictureBox2.Left + e.Location.X - pb2MouseOffset.X, PictureBox2.Top + e.Location.Y - pb2MouseOffset.Y)
		End If

	End Sub

	Private Sub PictureBox2_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseUp

		pb2MouseDown = False
		pb2StartPosition = Nothing

	End Sub
 
There is an error in my previous post in the MouseUp handler - it should be

Code:
    Private Sub PictureBox2_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseUp

        pb2MouseDown = False
        [s]pb2StartPosition = Nothing[/s]

    End Sub
 
Wow. This is very cool. I will hopefully get to try it tonight. You are awesome.....
 
Ok,
To start off it works really really cool on moving a picturebox. The problem is that is only works on a named picturebox (i.e. PictureBox2). I am needing Picturebox2 to stay put and then add to the form additional pictureboxes that sit infront of (appear to be one object to the end user) PictureBox2 and be able to move them around. Some will only have one of these smaller movable pictureboxes and others may have 5 to 6 images sitting on top of PictureBox2 that will need to be moved in place.

Is this possible???


Either way thank you so much for the code you have given up to this point.

Thom
 
Yes it is possible.

The main problem is that the moving code that I porovided requires local variables and whilst I am sure that there are many clever ways to overcome this problem I chose to create my own PictureBox control to solve it:

Code:
Public Class MyPictureBox
	Inherits PictureBox

	Private FMyMouseDown As Boolean = False
	Private FMyStartPosition As Point
	Private FMyMouseOffset As Point

	Public Property MyMouseDown() As Boolean
		Get
			Return FMyMouseDown
		End Get
		Set(ByVal value As Boolean)
			FMyMouseDown = value
		End Set
	End Property

	Public Property MyStartPosition() As Point
		Get
			Return FMyStartPosition
		End Get
		Set(ByVal value As Point)
			FMyStartPosition = value
		End Set
	End Property

	Public Property MyMouseOffset() As Point
		Get
			Return FMyMouseOffset
		End Get
		Set(ByVal value As Point)
			FMyMouseOffset = value
		End Set
	End Property

End Class

A simple "do nothing" class that is identical to the PictureBox except that it can now store the three extra values that are needed.

The moving code now needs to be modified to be more generic - I created a new form (Form2) and added a PictureBox (PictureBox1 - which will be the "hosting" control) and a Button (Button1 - to create the new PictureBoxes):

Code:
Public Class Form2

	Private Sub MyPictureBox_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

		Dim mypb As MyPictureBox = CType(sender, MyPictureBox)
		If e.Button = Windows.Forms.MouseButtons.Right Then
			With mypb
				RemoveHandler .MouseClick, AddressOf MyPictureBox_MouseClick
				RemoveHandler .MouseDown, AddressOf MyPictureBox_MouseDown
				RemoveHandler .MouseMove, AddressOf MyPictureBox_MouseMove
				RemoveHandler .MouseUp, AddressOf MyPictureBox_MouseUp
			End With
			mypb.Parent.Controls.Remove(mypb)
			mypb = Nothing
		End If

	End Sub

	Private Sub MyPictureBox_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

		Dim mypb As MyPictureBox = CType(sender, MyPictureBox)
		mypb.MyMouseDown = True
		If mypb.MyStartPosition = Nothing Then
			mypb.MyStartPosition = mypb.Location
			mypb.MyMouseOffset = e.Location
		End If

	End Sub

	Private Sub MyPictureBox_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

		Dim mypb As MyPictureBox = CType(sender, MyPictureBox)
		If mypb.MyMouseDown Then
			mypb.Location = New Point(mypb.Left + e.Location.X - mypb.MyMouseOffset.X, mypb.Top + e.Location.Y - mypb.MyMouseOffset.Y)
		End If

	End Sub

	Private Sub MyPictureBox_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

		Dim mypb As MyPictureBox = CType(sender, MyPictureBox)
		mypb.MyMouseDown = False

	End Sub

	Private mypb As MyPictureBox

	Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

		mypb = New MyPictureBox
		PictureBox1.Controls.Add(mypb)
		mypb.Image = Image.FromFile("C:\Users\Public\Pictures\Sample Pictures\forest.jpg")
		mypb.Location = PictureBox1.Location
		mypb.Size = New Size(20, 20)
		AddHandler mypb.MouseClick, AddressOf MyPictureBox_MouseClick
		AddHandler mypb.MouseDown, AddressOf MyPictureBox_MouseDown
		AddHandler mypb.MouseMove, AddressOf MyPictureBox_MouseMove
		AddHandler mypb.MouseUp, AddressOf MyPictureBox_MouseUp

	End Sub
End Class

As written the code above will not allow the MyPictureBoxes to move outside of PictureBox1's bounds (since this restriction seemed more appropriate based on your description of your requirements).

If you need to allow MyPictureBoxes to move freely change the line:
Code:
PictureBox1.Controls.Add(mypb)
to:
Code:
Me.Controls.Add(mypb)

As an aside the "F" prefix as used for the Private members in the MyPictureBox Class are a hang-over form my Delphi programming days!!!
 
A further thought...

Depending on the Location on the form of PictureBox1 the line:
Code:
mypb.Location = PictureBox1.Location
may give unexpected results. It would probably be better to place the MyPictureBox at a specific default location as in:
Code:
mypb.Location = New Point(10, 10)


Additionally....
If you decide that you want the Form to host the MyPictureBoxes then you would need:
Code:
		Me.Controls.Add(mypb)
		[b]mypb.BringToFront()[/b]
without BringToFront, the MyPictureBox would end up behind PictureBox1.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top