To start, hi to everyone im new to stackoverflow, and also new to programing (on 1ยบ year).
I've been searching but ive found nothing that answer my question, or maybe im just to newbie to understand the answers, so im sorry if its too simple, i cant see it!
/* my native lenguage is not english*/
Here is my problem, i'm making a VB form whit 200 pictureboxes that have to change or interact on click
i've made a control array whit all of them, like this:
Dim control(199) As PictureBox = Controles(control, 0)
Function Controles(ByRef control As Array, ByVal cont As Integer)
For Each pic As PictureBox In Me.Controls
control(cont) = pic
cont += 1
Next
Return control
End Function
this should asociate each picturebox to an array position, my problem now is how i can set the event handler to watch at control().click so no matter what box you click the event onclick will proc.
the only way i know is to create a click handler for each box manually.
hope i can find some answers
Using the Addhandler statement you can wire them all to the same routine. Then cast the sender object to interact with the PB that was clicked. OfType function.
Private Sub LoadME() Handles Me.Load
For Each pb As PictureBox In Me.Controls.OfType(Of PictureBox)()
'add all PB click events to a event sub
AddHandler pb.Click, AddressOf pb_Click
Next
End Sub
Private Sub pb_Click(sender As Object, e As EventArgs)
Dim pb = DirectCast(sender, PictureBox)
'this is the PB that was clicked
End Sub
Related
I'm adding controls to a FlowLayoutPanel like this:
Dim box As New PictureBox
(I'm making the controls using code, then I'm using FlowPanelLayout1.Controls.Add(box)).
How do I make these controls do things? In my code I'm using For Each, so multiple are made using this, my goal is to make each one be able to do what I want and the code for each would be different. How can I achieve this goal?
I believe what you're after is AddHandler. AddHandler allows you to programmatically assign code to an event at runtime. So you can create a Sub specifically to handle events from the picture boxes you create.
You can also retrieve the control that raised the event. This allows you to modify it, or access it's tag, allowing you to attach data to the PictureBox when you add it to the FlowLayoutPanel.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Create a new picturebox
Dim PB As New PictureBox With {.Size = New Drawing.Size(50, 50), .SizeMode = PictureBoxSizeMode.Normal}
PB.Image = Image.FromFile("res.png")
'Add it to the FlowLayoutPanel
FlowLayoutPanel1.Controls.Add(PB)
'Assign HandlePictureboxClick() to handle the PictureBox's DoubleClick event.
AddHandler PB.DoubleClick, AddressOf HandlePictureboxClick
End Sub
Public Sub HandlePictureboxClick(sender As Object, e As EventArgs)
'Retrive the control that raised the event (In this case, the one you double-clicked)
Dim Picturebox As PictureBox = CType(sender, PictureBox)
'Do whatever you want to do with it
Picturebox.SizeMode = PictureBoxSizeMode.Zoom
End Sub
The example above will change the PictureBox's size mode to zoom when the user double clicks on it, without modifying the other PictureBoxes in the FlowLayoutPanel
In my current VBA project I have several pictureboxes which will activate a messagebox when you click on one of them. Is there any way for me to get to know which of the pictureboxes was clicked? I've added the code I have currently which doesnt allow me to pass any information to the sub so each picturebox will active the exact same message.
AddHandler newPictureBox.Click, AddressOf pic_Click
Public Sub pic_Click()
MsgBox("test")
End Sub
I see above you are using VB2010. Try this...
AddHandler newPictureBox.Click, AddressOf pic_Click
Private Sub pic_Click(sender As Object, e As EventArgs)
Dim thisPic As PictureBox = DirectCast(sender, PictureBox)
'thisPIC now is a reference to the box, you can use .Name, etc. to get it's properties.
End Sub
You could add a different handler to each picturebox, which would then delegate to another sub, passing along the info about which picturebox was clicked.
Why don't you use the picturebox.click event?
Just double click on your picturebox and it will automatically be using that event.
Then you can add your own code into the picturebox.click so they will have their own function.
If that's not what you want, please describe what it is that you're trying to do more clearly.
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
So yes I'm very new to creating my own custom events. I can do the basics when I put controls on a form but this one is a little more complex. I have an application that reads in a .TSV and populates a form with controls based on the number of objects it "reads." So for instance: I have a file that contains 10 people objects and my code populates a form with controls for each person. Easy stuff!
Now lets say I have a ComboBox with the items: "Alive", "Deceased", "Unborn". Right next to this I have a textbox for age. Now originally, this textbox is not enabled because the default value for the ComboBox is "Unborn". But lets say when the user selects "Alive", I want that textbox to become enabled so an age can be entered.
Obviously from me asking this and the title of this question, I don't know how to go about doing this. I don't really understand events and I learn by example but the MSDN examples don't quite cut it.
Any help (especially an awesome Step-by-Step guide) would be greatly appreciated.
From what I gather from the comments, you want to add events to a form object that is created at runtime. Use the AddHandler command to the object. Something to the effect of:
AddHandler NameOfFormObject.TypeOfAction, AddressOf HowToHandle
Private Sub HowToHandle(ByVal sender as System.Object, ByVal e As System.EventArgs)
DropDownMenu.enabled = True
End Sub
Doing it this way, you will be able to modify the events of an object created at runtime. In your case, it sounds like you'll want to use the action that Josaph recommended, and end up incorporating both solutions offered, like so
AddHandler ComboBox1.SelectedIndexChanged, AddressOf HowToHandle
Private Sub HowToHandle(ByVal sender as System.Object, ByVal e As System.EventArgs)
If DirectCast(sender, ComboBox).SelectedIndex = 0 'Alive
DirectCast(DirectCast(sender, ComboBox).Tag, TextBox).enabled = True
Else
DirectCast(DirectCast(sender, ComboBox).Tag, TextBox).enabled = False
End If
End Sub
You will want to use the ComboBox_SelectedIndexChanged() event to capture that the combo box item has been changed. At that point, you will need to check to see which combo box item has been selected and make a decision as to whether the TextBox should be enabled or not. Here is an example. Note: This example assumes that "Alive" is the first item in your combobox at the 0 index.
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
If ComboBox1.SelectedIndex = 0 Then 'Alive
TextBox1.Enabled = True
Else
TextBox1.Enabled = False
End If
End Sub
Dynamically generate the combobox and add handler.
Dim cmb as New ComboBox
AddHandler cmb.SelectedIndexChanged, AddressOf ComboBox1_SelectedIndexChanged
Me.Controls.Add(cmb)
I suppose that as you will have 10 comboboxes... in the same way you'll have 10 textboxes.
In that case... once you attach and handle the event as AndyPerfect and Joseph... in that method you will need code something to know which of the Textboxs you need to enable/disable.
First you need to know which combobox triggered the event: this is done using the "sender" parameter. ctype(sender, Combobox) to access the methods and properties of the ComboBox.
Once you know which combo, you need to activate/deactivate the correct textbox.
To accomplish this, you'll need to add a reference to the TextBox in the "TAG" property of the Combobox at the moment of creating it.
Dim txt as new TextBox
Dim cmb as new ComboBox
cmb.Tag = txt
Then... you simple use:
ctype(ctype(sender, Combobox).Tag, TextBox).Enable = true
Here is how I ended up writing it in the end. I appreciate all the help! Thank you!
If DirectCast(sender, ComboBox).SelectedIndex = 2 Then
DirectCast(Me.Controls.Item(DirectCast(sender, ComboBox).Tag), TextBox).Enabled = True
Else
DirectCast(Me.Controls.Item(DirectCast(sender, ComboBox).Tag), TextBox).Enabled = False
End If
I have a flowLayoutPanel which I am programatically adding new panelLayouts to. Each panelLayout has a pictureBox within it. It's all working nicely, but I need to detect when that picture box is clicked on. How do I add an event to the picture? I seem to only be able to find c# examples....
my code to add the image is as follows...
' add pic to the little panel container
Dim pic As New PictureBox()
pic.Size = New Size(cover_width, cover_height)
pic.Location = New Point(10, 0)
pic.Image = Image.FromFile("c:/test.jpg")
panel.Controls.Add(pic)
'add pic and other labels (hidden in this example) to the big panel flow
albumFlow.Controls.Add(panel)
So I assume somewhere when I'm creating the image I add an onclick event. I need to get the index for it also if that is possible! Thanks for any help!
Use the AddHandler statement to subscribe to the Click event:
AddHandler pic.Click, AddressOf pic_Click
The sender argument of the pic_Click() method gives you a reference to the picture box back:
Private Sub pic_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim pic As PictureBox = DirectCast(sender, PictureBox)
' etc...
End Sub
If you need additional info about the specific control, like an index, then you can use the Tag property.
Substitute PictureBox1 with the name of your control.
Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click
'executes when PictureBox1 is clicked
End Sub