How change image in generated imagebox vb - vb.net

I have to do a program where I can generate Button, Label, ImageBox and work with them. Now I am searching how change image in created ImageBox, it writes: this element doesn't exist. How can I get access to the created elements?
Dim PictureB As New PictureBox
PictureB.Size = New System.Drawing.Size(200, 120)
PictureB.Location = New System.Drawing.Point(350, 20)
PictureB.BorderStyle = BorderStyle.Fixed3D
TabPage1.Controls.Add(PictureB)
"New sub"
OpenFileDialog1.ShowDialog()
PictureB.ImageLocation = OpenFileDialog1.FileName

PictureB is not accessible in your "new sub" because it only exists in the subprocedure that you created it in as a temporary, private variable. The PictureBox, however, that you created, does exist in TabPage1.Controls, so you can access it in a loop.
Based on your requirements, it seems that you also need to get the exact PictureBox that you created, so I would suggest adding a Name to it when you create it, something like PictureB.Name = "Pic1". I have included a sample Sub below that shows how you might accomplish your goal.
Public Sub SetImage(ByVal PictureBoxName As String)
If OpenFileDialog1.ShowDialog = DialogResult.OK Then
For Each c As Control In TabPage1.Controls
Dim pb As PictureBox = TryCast(c, PictureBox)
If Not IsNothing(pb) Then
If pb.Name = PictureBoxName Then
pb.ImageLocation = OpenFileDialog1.FileName
Exit For
End If
End If
Next
End If
End Sub
Alternatively, you could look into creating event handles instead: that would be more involved, but would be a good learning experience.

Related

Saving listbox's file not just its name

Im working on my first injector in VB.NET.
Im trying to save the loaded dll in listbox, but it only saves the name.
I select the dll, inject, it saves my.settings, but once I reopen the injector it only saves the dll's name, not its path, so I have to browse and select it again
I was thinking about maybe I have to save openfiledialog or something but really got no clue
Inject button:
My.Settings.dll = New Specialized.StringCollection
My.Settings.dll.AddRange(dll.Items.Cast(Of String).ToArray)
My.Settings.Save()
My.Settings.process = SteamTextBox2.Text
My.Settings.Save()
On form load:
If My.Settings.dll IsNot Nothing Then dll.Items.AddRange(My.Settings.dll.Cast(Of String).ToArray)
The problem with this the injector only needs the dll's name without path
Dim ExeName As String = IO.Path.GetFileNameWithoutExtension(Application.ExecutablePath)
Private Sub Inject()
pszLibFileRemote = OpenFileDialog1.FileName
End Sub
OpenFileDialog1.Filter = "DLL (*.dll) |*.dll"
OpenFileDialog1.ShowDialog()
OpenFileDialog1.ToString()
If IO.File.Exists(OpenFileDialog1.FileName) Then
Dim TargetProcess As Process() = Diagnostics.Process.GetProcessesByName(SteamTextBox2.Text)
If TargetProcess.Length = 0 Then
...
Else
Call Inject()
I want it to load the actual selected file not just it's name
Nothing is functionally wrong with your code. I guess the problem is with how you load the paths into the listbox in the first place. Here is some code to do that.
Add a new button called LoadButton, then this code for the handler
Private Sub LoadButton_Click(sender As Object, e As EventArgs) Handles LoadButton.Click
Dim filenames As IEnumerable(Of String)
Using dialog As New OpenFileDialog
dialog.Filter = "Application extensions (*.dll)|*.dll|All files (*.*)|*.*"
dialog.Multiselect = True
Select Case dialog.ShowDialog()
Case DialogResult.OK
filenames = dialog.FileNames
Case Else
filenames = Nothing
End Select
End Using
filenames = filenames.Select(Function(fn) System.IO.Path.GetFileName(fn))
If filenames?.Any() Then dll.Items.AddRange(filenames.ToArray())
End Sub
This will put the full path into the listbox. Does this solve the problem?

Can I use variables to control which PictureBox I am using?

Is there a way that I can use a variable to control which PictureBox I am using in Visual Basic?
I.e.:
CurrentNumber = 1
PictureBox(CurrentNumber).backcolour = backcolour
You can use the Me.Controls(String) indexer. It lets you specify the name (as a string) of the control you want to access, thus you can dynamically access a picture box by concatenating the string "PictureBox" with a number.
Dim TargetPictureBox As PictureBox = TryCast(Me.Controls("PictureBox" & CurrentNumber), PictureBox)
'Verifying that the control exists and that it was indeed a PictureBox.
If TargetPictureBox IsNot Nothing Then
TargetPictureBox.BackColor = Color.Red
End If
Alternatively, to save processing power by avoiding looping through the entire control collection every time you can call the OfType() extension on Me.Controls, storing the result in an array sorted by the controls' names. That way it'd only have to iterate the control collection once.
'Class level - outside any methods (subs or functions).
Dim PictureBoxes As PictureBox() = Nothing
'Doesn't necessarily have to be done in a button, it's just an example.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If PictureBoxes Is Nothing Then
PictureBoxes = Me.Controls.OfType(Of PictureBox).OrderBy(Function(p As PictureBox) p.Name).ToArray()
End If
'NOTE: CurrentNumber - 1 is necessary when using an array!
PictureBoxes(CurrentNumber - 1).BackColor = Color.Red
End Sub
NOTE: This solution will only work properly if all your picture boxes are named "PictureBox1", "PictureBox2", etc. If you suddenly skip a number ("PictureBox3", "PictureBox5", "PictureBox6") then PictureBoxes(CurrentNumber - 1) for CurrentNumber = 5 would return PictureBox6 rather than PictureBox5.
What you really should do is create a PictureBox() and use that to reference your picture boxes via an index.
The best way to build your array is to create a method that builds the array from the references created by the designer. This lets you continue to use the designer to create your controls and it makes your code check for deleted controls at design-time. Using Me.Controls(...) suffers from run-time errors if controls you are looking for have been deleted.
Here's the code you need:
Private _PictureBoxes As PictureBox() = Nothing
Sub AssignPictureBoxesArray
_PictureBoxes = {PictureBox1, PictureBox2, PictureBox3}
End Sub
Then you access them like this:
Sub SomeMethod
Dim CurrentNumber = 1
Dim PictureBox = _PictureBoxes(CurrentNumber - 1)
PictureBox.BackColor = System.Drawing.Color.Red
End Sub

Get image location using a drag and drop

I have a drag and drop event to get images into a picture box. I need to get the image location to string to store on my database. I can get the location if I use a OpenFileDialog, but if I use a drag and drop, I can't seem to get it. Here is my code:
Private Sub picCategoryImage_DragEnter(sender As Object, e As DragEventArgs) Handles picCategoryImage.DragEnter
'Procedure to copy the dragged picture from the
'open window
If e.Data.GetDataPresent(DataFormats.FileDrop) Then
'If the file explorer is open, copy the picture to the box
e.Effect = DragDropEffects.Copy
picCategoryImage.BorderStyle = BorderStyle.FixedSingle
TextBox1.Text = picCategoryImage.ImageLocation
Else
'otherwise, don't take action
e.Effect = DragDropEffects.None
btnDeleteImage.Visible = False
End If
End Sub
Private Sub picCategoryImage_DragDrop(sender As Object, e As DragEventArgs) Handles picCategoryImage.DragDrop
'Procedure to select the pictue and drag to picturebox
Dim picbox As PictureBox = CType(sender, PictureBox)
Dim files() As String = CType(e.Data.GetData(DataFormats.FileDrop), String())
If files.Length <> 0 Then
Try
picbox.Image = Image.FromFile(files(0))
btnDeleteImage.Visible = True
picbox.BorderStyle = BorderStyle.None
picCategoryImage.BringToFront()
btnDeleteImage.BringToFront()
Catch ex As Exception
MessageBox.Show("Image did not load")
End Try
End If
End Sub
As suggested by Plutonix, you're already using the file path so you've already got it. That's how Image.FromFile is able to create an Image from a file. If you mean that you need to be able to get the path later then you have two main choices:
Do as you're doing and store the path in a member variable for later use.
Instead of calling Image.FromFile and setting the Image of the PictureBox, just call the Load method of the PictureBox. You can then get the path from the ImageLocation property.
I would actually suggest using option 2 regardless, because it has the added advantage of not locking the file the way your current code does.

Retrieving data on dynamic controls

I am using dynamically created controls and need to retrieve information about the control at runtime.
If IsLoaded <> "free" Then
flow_display.Controls.Clear()
For x As Integer = 0 To populate.Count - 1
If populate(x).parentID = 2 Then
Dim NewPicBox As PictureBox = New PictureBox
NewPicBox.Size = New System.Drawing.Size(697, 50)
NewPicBox.ImageLocation = pw_imgLink & populate(x).imageID
AddHandler NewPicBox.Click, AddressOf catWindow
flow_display.Controls.Add(NewPicBox)
End If
Next
IsLoaded = "free"
End If
End Sub
Here I create the control when the user clicks on the appropriate label. Right now the catWindow sub is empty. I need to figure out which button is clicked and figure out its location on the populate list. I have tried a few things and from what I've read from other questions can't seem to find anything the helps. Thanks :)
For finding out which PictureBox is pressed, your catWindow Sub should look like this:
Public Sub catWindow(ByVal sender As Object, ByVal e As EventArgs)
Dim box As PictureBox = TryCast(sender, PictureBox)
If box Is Nothing Then Exit Sub
'Now "box" refers to the PictureBox that was pressed
'...
End Sub
If you want to find it's location in the populate list, you will need to iterate through the list until you find the matching box. You could also pre-empt a property on your PictureBox that isn't doing anything else and use it to store the index. Older forms tools used to have a .Tag property especially for this kind of thing. But really, the need to do this smells like a design flaw to me.
FWIW, I'd rewrite your original sample like this:
If IsLoaded <> "free" Then
flow_display.SuspendLayout()
flow_display.Controls.Clear()
For Each box As PictureBox In populate
.Where(Function(p) p.parentID = 2)
.Select(Function(p) New PictureBox() With {
.Size = New System.Drawing.Size(697, 50),
.ImageLocation pw_imgLink & p.imageID })
AddHandler box.Click, AddressOf catWindow
flow_display.Controls.Add(box)
Next box
flow_display.ResumeLayout()
IsLoaded = "free"
End If

How to change only one tooltip?

I am populating a FlowLayout with Pictureboxes. As I populate i give each of them a tooltip. I have a seperate function to change the pictures how can I change the tooltip as well?
dim laytt as tooltip = new tooltip
For i = 1 To count
Dim newPic As PictureBox = New PictureBox()
newPic.Image = p.Image
newPic.Size = p.Size
newPic.SizeMode = p.SizeMode
laytt.SetToolTip(newPic, ttstring)
AddHandler newPic.Click, AddressOf LayoutComponent_Clicked
sys.Add(a_component)
LayoutFlowLayout.Controls.Add(newPic)
Next
later i have a function to change the pics in it I want to be able to change the tool tip
Private Sub LayoutComponent_Clicked(ByVal sender As Object, ByVal e As EventArgs)
Dim i As Integer = LayoutFlowLayout.Controls.IndexOf(sender)
If deleteModeOn Then
sys.components.RemoveAt(i)
LayoutFlowLayout.Controls.RemoveAt(i)
Exit Sub
End If
'get index in sys from layout?
If (sys.components.Item(i).GetType() = GetType(Transpositor)) Then
Form2.ShowDialog(Me)
sys.components.Item(i).divert = tempTranspositorDivert
'here I want to do something like this
laytt.RemoveAt(i) <--- THIS DOESN'T EXIST
End If
End Sub
TL;DR I want to remove/change only one tooltip text at a specific index
Since the sender parameter is the picture box control that was clicked, you can use that variable to specify which control you want to alter. For instance, this will remove the tool tip:
laytt.SetToolTip(sender, Nothing)
This will change it:
laytt.SetToolTip(sender, "new value")