I am working on a project and I have a label in a picturebox that I need to drag around and while dragging around have it leave a black trail on the picturebox. I am stumped as to how to make this happen. The label is 15x15 and is moved using the mouse and mousedown, mousemove, and mouseup events. During the mousemove the label needs to draw black wherever the label has covered. Thanks for the help!
You need to override the Form's OnPaint() method and then track the offset of the mouse Location from the point of drag origniation. This is essentially implementing an animated effect, so you will need to fire a redraw timer on the Label's drag start, paint the "tail" at a previous drag coordinate, repeating as your drag op moves the mouse coordinates past a certain threshold or certain speed. This will require some playing around to get the effect just right, but its fairly easy to implement.
Get started here: http://msdn.microsoft.com/en-us/library/3e40ahaz(v=vs.110).aspx
Lets say you have a background image in picturebox. Create a bitmap with picturebox dimensions:
Private pctBoxImage As Bitmap
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
pctBoxImage = New Bitmap(PictureBox1.Width, PictureBox1.Height, Drawing.Imaging.PixelFormat.Format24bppRgb)
pctBoxImage = CType(PictureBox1.BackgroundImage, Bitmap)
End Sub
If you dont have a background image just some color:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
pctBoxImage = New Bitmap(PictureBox1.Width, PictureBox1.Height, Drawing.Imaging.PixelFormat.Format24bppRgb)
Dim objGraphics As Graphics = Graphics.FromImage(pctBoxImage)
objGraphics.Clear(PictureBox1.BackColor)
objGraphics.Dispose()
End Sub
When ever you move the label:
Dim pt as Point
'pt = PictureBox1.PointToClient(Cursor.Position)
pt = Label1.PointToScreen(New Point(0, 0))
pt = PictureBox1.PointToClient(pt)
Dim objGraphics As Graphics = Graphics.FromImage(pctBoxImage)
objGraphics.FillRectangle(Brushes.Black, pt.X, pt.Y, 15, 15)
objGraphics.Dispose()
PictureBox1.BackgroundImage = pctBoxImage
valter
Related
I'm doing a project for my kitten who died...
I would like to know how I make it flip (look at the right side) when it comes to the left side of the screen, I'll leave an example in the print
Here's some code you can use to start with a single image file and display it in its original form or flipped horizontally depending on the horizontal position of its PictureBox on the screen.
'The Image to display on the left side of the screen.
Private leftImage As Image
'The Image to display on the right side of the screen.
Private rightImage As Image
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Assume that the original image is the one to display on the left.
leftImage = Image.FromFile("file path here")
'Create a mirror image to display on the right.
rightImage = leftImage.Clone()
rightImage.RotateFlip(RotateFlipType.RotateNoneFlipX)
End Sub
Private Function IsPictureBoxOnLeftSideOfScreen() As Boolean
Dim screenMiddle = Screen.PrimaryScreen.WorkingArea.Width \ 2
Dim pictureBoxMiddle = PictureBox1.PointToScreen(Point.Empty).X + PictureBox1.Width \ 2
Return screenMiddle > pictureBoxMiddle
End Function
Private Sub SetImage()
PictureBox1.Image = If(IsPictureBoxOnLeftSideOfScreen(), leftImage, rightImage)
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
rightImage.Dispose()
leftImage.Dispose()
End Sub
Where you call that SetImage method depends on exactly how you're moving the PictureBox, which you never showed us. If you're moving the form then you might do so in the LocationChanged event handler of the form. If you're moving the PictureBox then you might do so in the LocationChanged event handler of the PictureBox.
It works fine until I click it and pop up a file dialog box,and then white lines appears surrounding it.
I don't know how to remove these ugly lines.
The only code is openFileDialog1.ShowDialog().
It's a Button whose FlatStyle is flat and whose BackgroundImage is a PNG image.
After that the white lines appears, and if I click the Form it will disappear.
A simple workaround is to set the Button FlatAppearance.BorderColor to its Parent.BackColor. It will overwrite the focus rectangle. The MouseUp event can be used to set the value, it will be raised before a new Window is opened (the Control.Leave event will never be raised):
Private Sub SomeButton_MouseUp(sender As Object, e As MouseEventArgs) Handles SomeButton.MouseUp
Dim ctl As Button = DirectCast(sender, Button)
ctl.FlatAppearance.BorderColor = ctl.Parent.BackColor
End Sub
Using the Control.Paint event, we can also use the Control.BackColor property to paint the border, both with the ControlPaint class DrawBorder method (simpler than using the ButtonRenderer class):
Private Sub SomeButton_Paint(sender As Object, e As PaintEventArgs) Handles SomeButton.Paint
Dim ctl As Button = DirectCast(sender, Button)
ControlPaint.DrawBorder(e.Graphics, ctl.ClientRectangle, ctl.BackColor, ButtonBorderStyle.Solid)
End Sub
and painting the Control's border ourselves:
(Note that the ClientRectangle size must be shrinked, by 1 pixel, both in the Width and Height dimensions. This is by design).
Private Sub SomeButton_Paint(sender As Object, e As PaintEventArgs) Handles SomeButton.Paint
Dim ctl As Control = DirectCast(sender, Control)
Dim r As Rectangle = ctl.ClientRectangle
Using pen As Pen = New Pen(ctl.BackColor, 1)
e.Graphics.DrawRectangle(pen, r.X, r.Y, r.Width - 1, r.Height - 1)
End Using
End Sub
I have a Picture Box called BGImage. I hope that when the user clicks on this I can capture the position of the mouse relative to BGImage.
I've tried using MousePosition, only to find it gives the mouse location on the screen, not on the PictureBox.
So I also tried using PointToClient:
Dim MousePos As Point = Me.PointToClient(MousePosition)
But this gives me the location {X=1866,Y=55} whereas I actually clicked on the PictureBox at around {X=516,Y=284}.
I think the problem arises because I have full-screened my program and set the position of the PictureBox to be at the centre of the screen (BGImage.Location = New Point((My.Computer.Screen.WorkingArea.Width / 2) - (1008 / 2), ((My.Computer.Screen.WorkingArea.Height / 2) - (567 / 2))))
I should also mention that the size of the PictureBox is 1008 By 567 pixels and my screen resolution is 1366 by 768.
Is there any way I can get the mouse position relative to BGImage's position?
Add a mouse click event to your picture box
Then use the MouseEventArgs to get the mouse position inside the picture box.
This will give you the X and the Y location inside the picture box.
Dim PPoint As Point
Private Sub PictureBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseClick
PPoint = New Point(e.X, e.Y)
MsgBox(Convert.ToString(PPoint))
End Sub
I have before the same problem and just solved with the help of some friends.
Give a look Here mouse position is not correct
Here its the code that give you the correct position of the Mouse Based On A Picture.
Tanks to #Aaron he have give a final solution to this problem.
This will put a red dot on the exact point you click. I wonder how useful setting the cursor position will be though, as they will almost certainly move the mouse after clicking the button (inadvertently or not).
Setting the Cursor position needs to be in Screen coordinates - this converts back to client coordinates for drawing. I don't believe the PointToClient is necessary for the cursor position. In the below code, it is an unnecessary conversion, as you just go back to client coordinates. I left it in to show an example of each conversion, so that you can experiment with them.
Public Class Form1
Private PPoint As Point
Public Sub New()
' This call is required by the designer.
InitializeComponent()
PictureBox1.BackColor = Color.White
PictureBox1.BorderStyle = BorderStyle.Fixed3D
AddHandler PictureBox1.MouseClick, AddressOf PictureBox1_MouseClick
AddHandler Button8.Click, AddressOf Button8_Click
' Add any initialization after the InitializeComponent() call.
End Sub
Private Sub Button8_Click(sender As Object, e As EventArgs)
Dim g As Graphics = PictureBox1.CreateGraphics()
Dim rect As New Rectangle(PictureBox1.PointToClient(PPoint), New Size(1, 1))
g.DrawRectangle(Pens.Red, rect)
End Sub
Private Sub PictureBox1_MouseClick(sender As Object, e As MouseEventArgs)
PPoint = PictureBox1.PointToScreen(New Point(e.X, e.Y))
Label8.Text = PPoint.X.ToString()
Label9.Text = PPoint.Y.ToString()
End Sub
End Class
Instead of using:
Dim MousePos As Point = Me.PointToClient(MousePosition)
You should be using:
Dim MousePos As Point = BGImage.PointToClient(MousePosition)
It will give you mouse position in BGImage coordinates, whereas the first code gives you the mouse position in the Form's coordinates.
The following code does not work:
Private Sub panelButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles panelButton.Click
Dim myBrush As Brush
myBrush = New SolidBrush(Color.Yellow)
fBitmap = New Bitmap(picturePanel.Width, picturePanel.Height)
Dim gg As Graphics = Graphics.FromImage(fBitmap)
gg.Clear(Color.White)
'<<<<<my attempt<<<<<<
Dim rec As Rectangle
rec = New Rectangle(picturePanel.Location.X, picturePanel.Location.Y, picturePanel.Width, picturePanel.Height)
gg.FillRectangle(myBrush, rec)
'<<<<<<<<<<<<<<<<<<<<<
'gg.FillRectangle(myBrush, gg.ClipBounds) '<<actual answer
gg.Dispose()
picturePanel.Refresh()
End Sub
In the Panel's repaint handler I've got this:
Private Sub picturePanel_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles picturePanel.Paint
If fBitmap IsNot Nothing Then
e.Graphics.DrawImage(fBitmap, 0, 0)
End If
End Sub
I've included the recommended code (marked as actual answer) but why doesn't the section marked my attempt turn the panel yellow? - can it be tweaked so that it turns the panel yellow?
rec = New Rectangle(picturePanel.Location.X, picturePanel.Location.Y, _
picturePanel.Width, picturePanel.Height)
That's the wrong rectangle. It is relative from the panel's Parent instead of the panel itself. At best you'll see the rectangle at the far right-bottom corner. Or not at all if it is off the bitmap. Draw relative to the bitmap's upper left corner instead. Fix:
rec = New Rectangle(0, 0, fBitmap.Width, fBitmap.Height)
Do note that you'll no longer see any white since you completely overdrew that. It isn't clear what you meant to do. Perhaps more illustrative is to give it a yellow border:
rec = New Rectangle(0, 0, fBitmap.Width-1, fBitmap.Height-1)
gg.DrawRectangle(Pens.Yellow, rec)
Do favor the Using statement instead of the explicit Dispose() call. Also use it on the brush, it should be disposed as well.
I am trying to create a simply bouncy ball application in VB net;
I am using a timer and the FillEllipse() method to try ad create a new circle at every tick of the timer.
Code:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim Gr As Graphics = Me.CreateGraphics
Gr.FillEllipse(Brushes.Teal, X, Y, W, H)
CollisionDetect()
X = X + X_Dir
Y = Y + Y_Dir
Gr.Dispose()
End Sub
The result? The form continously draws onto itself, without clearing the last circle. This means that you end up with a 'line' of spheres together.
To clarify:
X is well, the X-Coords
Y is Y- Y-Coords
X_Dir is an integer, it is added to every iteration of the loop so the next time the loop iterates, it'll be at a different location;
Y_Dir is the same but for the Y Coords;
CollisionDetect() Is empty. It is yet to be filled, it will handle the collision with the sides of the forms.
W, H are width and height, respectively.
Ideas?
Usually painting is done when the Paint event is fired. Add a Panel control with the desired background color to your form. Handle the Paint event of your panel
Private Sub Panel1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
e.Graphics.FillEllipse(Brushes.Teal, X, Y, W, H)
End Sub
The panel will always automatically be cleared before you draw.
Change the timer tick event handler to
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Panel1.Invalidate() ' This triggers the Paint event
CollisionDetect()
X = X + X_Dir
Y = Y + Y_Dir
End Sub
Note that the Paint event is fired automatically, if the panel was hidden by another form, for instance, and has to be redrawn. If the computer is busy and cannot paint, some paint events may be skipped. Therefore keep your game logic (calculation) in Timer1_Tick.
If you prefer to draw directly on the form, you can do that by using the form's paint event instead of the panel's paint event and by calling Me.Invalidate() instead of Panel1.Invalidate().