Display an image in picturebox from specific position - vb.net

I have a picturebox that "works" as button. I have load an image map as background image, to use it for buttons conditions (click, hover etc).
As default, background image shows it's top left position, the first icon. Let's say, how can I move (x) to 32px and (y) to 64? Something like css styles background-position: 32px 64px; for example.

If you need to reposition the image then I wouldn't use a PictureBox, just a Panel or draw the image on the surface of the form.
It is possible though with the following code. Notice that it removes the PictureBox's Image so you are losing the functionality of a PictureBox.
Public Class Form1
Private _moveIt As Boolean = False
Private _coyote As Image
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
_coyote = PictureBox1.Image
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
_moveIt = True
PictureBox1.Invalidate()
End Sub
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
If _moveIt = True Then
PictureBox1.Image = Nothing
e.Graphics.DrawImage(_coyote, New Rectangle(New Point(32, 64), _
New Size(_coyote.Width, _coyote.Height)))
End If
End Sub
End Class
To keep the PcitureBox's functionality (to use its Image property) you would have to create a new image which is a transformed version of the original image.

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

PictureBox2.Image = PictureBox1.Image seems to be linking the boxes instead of copying the image over?

The Problem
I have a simple form with 2 PictureBoxes
I allow the user to draw on PictureBox1
When I click a Button on the form I want to capture the image in PictureBox1 and store it in PictureBox2
The issue is that if I add the line:
PictureBox2.Image = PictureBox1.Image
Any updates to PictureBox1 are immediately reflected in PictureBox2 ?!?
I just want to capture the image in PictureBox1 at that moment in time so that I can use it to 'Undo'
Tech
It's a Windows Forms App in Visual Basic, .Net 4.7.2 using Visual Studio 2019 Preview
Code
Public Class Form1
Dim drawMouseDown = False ' Set initial mouse state to not clicked
Dim drawMyBrush As New Pen(Brushes.White, 20) 'Set up the Brush
Public drawCanvas As New Bitmap(245, 352) 'Set up Bitmap Canvas
Private Sub btn_Color_Yellow_Click(sender As Object, e As EventArgs) Handles btn_Color_Yellow.Click
drawMyBrush.Brush = Brushes.Yellow
drawMyBrush.Width = 20
End Sub
Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
drawMouseDown = True
End Sub
Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
drawMouseDown = False
End Sub
Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
Dim g As Graphics = Graphics.FromImage(drawCanvas)
Static coord As New Point
If drawMouseDown Then
g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
drawMyBrush.StartCap = Drawing2D.LineCap.Round
drawMyBrush.EndCap = Drawing2D.LineCap.Round
g.DrawLine(drawMyBrush, coord.X, coord.Y, e.X, e.Y)
g.Dispose()
PictureBox1.Image = drawCanvas
Me.Refresh()
End If
coord = e.Location
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PictureBox2.Image = PictureBox1.Image 'Why does this not just update the PicBox2 image once?!? (or only when the Button is clicked)
End Sub
End Class
Expectation
When Button1 is clicked I expect PictureBox2 to contain the PictureBox1 image, when I continue to draw on PictureBox1 I do NOT expect it to keep updating PictureBox2 as the user is drawing on the other!
As you suspect, PictureBox2.Image = PictureBox1.Image makes the former a reference to the latter.
What you can do instead is clone the image:
PictureBox2.Image = DirectCast(PictureBox1.Image.Clone(), Image)
Because you are referencing the Image property of PictureBox2 to PictureBox1.Image. So when they both point to the same reference, any changes to either of the PictureBox's image property, will affect the other's.
In order to avoid his, make a new instance of Bitmap object based on the PictureBox1.Image and set it to PictureBox2.Image:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PictureBox2.Image = New Bitmap(PictureBox1.Image)
End Sub

VB.NET Find a Pixel Color of an Image

How Can I find the HEX color of a specific image pixel? I've Tried This:
Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
PictureBox1.Image = Image.FromFile("c:\image.jpg")
PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
Dim b As Bitmap = Me.PictureBox1.Image
Dim ver As String = b.GetPixel(e.X, e.Y).ToString
Dim veri As String = Hex(b.GetPixel(e.X, e.Y).ToArgb)
End Sub
This doesn't work as expected:
Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
PictureBox1.Image = My.Resources.MyImage
PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
Dim b As Bitmap = Me.PictureBox1.Image 'b is not streched..?
Dim ver As String = b.GetPixel(e.X, e.Y).ToString
Dim veri As String = Hex(b.GetPixel(e.X, e.Y).ToArgb)
End Sub
How can I fix this?
I'll post this as an answer because I want to post some code. You seem to be under the impression that setting the SizeMode of a PictureBox does/should affect the Image it contains. It doesn't and it shouldn't. That property is for the UI only, i.e. it affects what the user sees but has no effect on the data. To prove that to yourself, try creating a WinForms app with two PictureBoxes and two Buttons and add this code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PictureBox1.Image = Image.FromFile("image file path here")
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If PictureBox1.SizeMode = PictureBoxSizeMode.Normal Then
PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
Else
PictureBox1.SizeMode = PictureBoxSizeMode.Normal
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
PictureBox2.Image = PictureBox1.Image
MessageBox.Show(PictureBox2.Image.Size.ToString())
End Sub
You can set the image path to any file you want.
If you click Button2 you'll see the same image appear in PictureBox2 as in PictureBox1 and the dimensions will be displayed. If you click Button1 you'll see the image in PictureBox1 change dimensions to fit the control. If you click Button2 again, what you see in PictureBox2 won't change and neither will the dimensions displayed, because the Image object hasn't changed.
If you want to get the colour of the pixel under the mouse cursor then you'd need to call DrawToBitmap on the control itself to get a Bitmap of what's actually displayed on the screen.

Drawing rectangle on picture box from another form's button

I have a form with a picturebox on it, and another form with a button on it. How would I picturebox1_paint on the first form once I press the button on the other form?
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
e.Graphics.DrawRectangle(Pens.Blue, x.text, y.text, width.text, height.text)
End Sub
this is what I have, what would I need to alter to get it to work?
At Form1, add
Sub PaintImage(rectangle As Rectangle)
' create image in size of PictureBox1
Dim image As New Bitmap(PictureBox1.Width, PictureBox1.Height)
' paint on created image
Using gr As Graphics = Graphics.FromImage(image)
gr.DrawRectangle(New Pen(Color.Red), rectangle)
End Using
' display finished image in PictureBox1
PictureBox1.Image = image
End Sub
and call it from the form with button:
Sub Button1_Click(sender as Object, e as EventArgs) Handles Button1.Click
Form1.PaintImage(New Rectangle(x, y, width, height)) ' assume we already have x, y, w, h
End Sub
You can delete your Paint() event handler shown in the question. Its purpose is to repaint PictureBox1.Image if its size or visibility is changed and in most cases you can leave it as it is.

Graphics.DrawRectangle not working in control events

First of all thank you for taking the time out of your busy schedule to assist me.
I am developing a project (Win Application) with a Form and 3 textboxes (TextBox1, TextBox2 and TextBox3).
I need draw a rectangle around the textbox when focused this.
The code is:
Private Sub TextBox123_Enter(sender As Object, e As System.EventArgs) Handles TextBox1.Enter, TextBox2.Enter, TextBox3.Enter
Using g As Graphics = Me.CreateGraphics
Dim r As Rectangle = sender.Bounds
r.Inflate(4, 4)
g.DrawRectangle(Pens.Blue, r)
End Using
End Sub
The problem is the following:
The first time the textbox1 gains focus rectangle is not drawn.
The first time the textbox2 gains focus rectangle is not drawn.
Why not the rectangle is drawn when the first two events enter are fired?
Drawing with CreateGraphics is almost always not the correct approach. If you notice also, when you move from one box to another, the old rectangle is not being erased. You need to use the Form_Paint event to get it to work right. Or...perhaps simpler would be to create a UserControls which is 1-2 pixels larger than a child TextBox and set the backcolor of the UserControl canvas, draw your rectangle when the control gets the focus.
For form paint:
Public Class Form1
Private HotControl As Control
If you are only going to do TextBoxes, you can declare it As TextBox. This way it allows you to do the same for other control types. Set/clear the tracker:
Private Sub TextBox3_Enter(sender As Object, e As EventArgs) Handles TextBox3.Enter,
TextBox2.Enter, TextBox1.Enter
HotControl = CType(sender, TextBox)
Me.Invalidate()
End Sub
Private Sub TextBox1_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave,
TextBox2.Leave, TextBox3.Leave
HotControl = Nothing
Me.Invalidate()
End Sub
The Me.Invalidate tells the form to redraw itself, which happens in Paint:
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
If HotControl IsNot Nothing Then
Dim r As Rectangle = HotControl.Bounds
r.Inflate(4, 4)
e.Graphics.DrawRectangle(Pens.Blue, r)
End If
End Sub
You should also turn on Option Strict.
Try this in the click event handler
Private Sub TextBox1_Click(sender As Object, e As EventArgs) Handles TextBox1.Click
Using g As Graphics = Me.CreateGraphics()
Dim rectangle As New Rectangle(TextBox1.Location.X - 1, _
TextBox1.Location.Y - 1, _
TextBox1.Size.Width + 1, _
TextBox1.Size.Height + 1)
g.DrawRectangle(Pens.Blue, rectangle)
End Using
End Sub