Determine an object's runtime X-location - vb.net

This might be a stupid question, but I'm attempting to move a button to the left by roughly 160 pixels each time the button is pressed. However, I need to know what the x-location is of the object at runtime so I can dynamically add those 160 pixels to it. A real world example of this would be right above (if you happen to be using chrome/firefox-which who isn't?) when the new tab button moves every time a new tab is opened (additionally subtracting those pixels too which is harder because I have to figure out how to handle the tab close event within a QTab control in the QIOS devsuite).

You could do this:
Button1.Location = New Point(Button1.Location.X - 160, Button1.Location.Y)
or this:
Dim pt As Point = Button1.Location
Button1.Location = New Point(pt.X - 160, pt.Y)
or maybe this:
Dim pt As Point = Button1.Location
pt.Offset(-160, 0)
Button1.Location = pt

When you use the WinForm designer, each control on your form is assigned a unique name. When you place a control on the form, the designer automatically assigns a unique name (e.g. Button1), but you can change it to whatever you want. The designer automatically creates a class-level variable (i.e. field) for each control. The name of the variable matches the name of the control. So, for instance, if you call your control Button1, then you can access the X-location of that button via the Button1 variable, like this:
Dim x As Integer = Button1.Left
If you are writing code that is intended to handle events from multiple controls, so you wouldn't know which variable to use, you can use the event handler's sender parameter. Every event handler has a sender As Object parameter which points to the control that is raising the event.
So, for instance, in a the click event, you could do something like this:
Private Sub ClickHandler(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click, Button3.Click
Dim clickedButton As Button = DirectCast(sender, Button)
Dim x As Integer = clickedButton.Left
End Sub

Related

Refer to a determinate created button

So In my program I’ve putted a flowlayourpanel and with a button I add to the layout infinite new buttons
(button.name = “button” + i.tostring) [i = i + 1]
With another button I want to hide the button with the i=3 so button3.hide(), but it doesn’t work beacause it doesn’t exist yet so How can I refer to the button created when the i was 3?
Name is a property of the Control class so every control has that property. That doesn't mean that it needs to be set though, so some controls don't have a name. When you add a control to your form in the designer, what happens is that the Name property is set AND a field is declared with that name. That's why, if you name a Button control Button1, you are able to use the field Button1 to refer to it.
When you create controls at run time, of course there is no field dedicated to that control so of course you can use such a dedicated field to refer to it. It's up to you to get a reference to that control from wherever you put it when you created it. Where that is is up to you but, if you added it to the Controls collection of a container, that is one option for getting it back. If you set the Name property, you can index the Controls collection with that name to get it, e.g.
Dim myButton = DirectCast(myFlowLayoutPanel.Controls("Button" & i), Button)
There may be other ways of getting that reference too. For instance, if you created your own List(Of Button) and set the Tag of each Button to the number, you could do this:
Dim myButton = myButtonList.Single(Function(btn) CInt(btn.Tag) = i)
When adding your buttons to the FlowLayoutPanel you have correctly assinged a name. You can use this name to refer to the button as shown in Button2.Click.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For i = 1 To 5
Dim b As New Button
b.Name = "btn" & i
b.Text = "btn" & i
FlowLayoutPanel1.Controls.Add(b)
Next
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
FlowLayoutPanel1.Controls("btn3").Visible = False
End Sub

How to remove the most recently added control?

I Intended to display an PictureBox in my form when the mouse hovered over another control. I then wanted to use a separate event for when the mouse left the control. This event would remove the displayed PictureBox from controls. However, because my events are private subs, I can't directly access the name of the control in the latter event. A solution to this would be a method that removes the most recently added control. If no such method exists, or there is an alternative way of approaching this problem, any help would be appreciated.
I tried simply using Controls.Remove(), but this requires a parameter. The name of the control as a string did not work either, as the parameter must be a control itself.
Private Sub Tile_MouseEnter(Sender As Object, e As EventArgs)
Dim CloseUpPic As New PictureBox With {Properties}
CloseUpPic.Image = Sender.Image
Controls.Add(CloseUpPic)
Refresh()
End Sub
Private Sub Tile_MouseLeave(Sender As Object, e As EventArgs)
Me.Controls.Remove()
End Sub
The program won't compile due to .Remove() needing a parameter
I expected for the Control to be created and displayed when the mouse entered the tile, and to cease to exist when the mouse left the tile.
For future reference, controls have Tag property which allows you to store whatever you like. In this case, you can store a reference to the newly created PictureBox. Furthermore, the "Sender" parameter tells you which control was the source of the event. You can cast sender to a control, then store the reference. Then, in the leave event, you can cast sender to a control, cast the .Tag to a control, and finally remove it:
Private Sub Tile_MouseEnter(Sender As Object, e As EventArgs)
Dim ctl As Control = DirectCast(Sender, Control)
Dim CloseUpPic As New PictureBox With {Properties}
CloseUpPic.Image = Sender.Image
Controls.Add(CloseUpPic)
ctl.Tag = CloseUpPic
Refresh()
End Sub
Private Sub Tile_MouseLeave(Sender As Object, e As EventArgs)
Dim ctl As Control = DirectCast(Sender, Control)
Dim ctlToRemove As Control = DirectCast(ctl.Tag, Control)
Me.Controls.Remove(ctlToRemove)
End Sub
I ended up using the following code to solve my issue:
For Each Closeup In Controls.OfType(Of CloseUp)
Controls.Remove(Closeup)
Next
I created a new class of my own called Closeup, that inherits PictureBox. I then looped through each Closeup in controls (There was only one but this code works for multiple controls), and removed them.

How to create any one dynamic controls with a for loop without using location property and the form should grow automatically

How to create multiple button controls with a for loop without getting the controls overlapped and without using location property in Vb.Net.
I have created 'n' number of vb controls dynamically but the created controls are getting overlapped to each other. When I use location property to each controls all the controls are getting displayed as per the location value.
The real problem is, I'm using a panel of width 300 and height 300, under that I need to display the dynamically created controls. I have figured it out which is tedious work and does take a lot of time. My idea is to find the panel width and height then need to check whether the new control which is getting created has ample of space to fit inside the panel.
I need to know few things,
1) How to display the controls dynamically using for loop without getting overlapped over each other and without using location property.
2) I need the container or the panel to grow as per the number of controls which gets created dynamically.
3) Accessing each controls which got displayed using an ID or educate or explain me any better idea.
I created a new WinForms project and added a Button to the top of the form. I added a FlowLayoutPanel under that and made it narrow enough to fit a single Button widthwise. I set the AutoSize property of the FLP to True and the FlowDirection to TopDown. I then added this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Create the new Button.
Dim btn As New Button
'Add it to the FLP
FlowLayoutPanel1.Controls.Add(btn)
'Get the position of the bottom, left of the Button relative to the form.
Dim pt = PointToClient(btn.PointToScreen(New Point(0, btn.Height)))
'Resize the form to provide clearance below the new Button.
ClientSize = New Size(ClientSize.Width, pt.Y + 10)
End Sub
I then ran the project and started clicking the Button I added. As expected, each click added a new Button to the FLP in a vertical column and the form resized to fit. In order to access such controls in code, you can simply index the Controls collection of the FLP.
try this helps you.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
'Do Something
Else
'Do Something else
End If
Panel1.Controls.Clear()
For i As Integer = 0 To 10 Step 1
Dim b15 As New Button
b15.Text = "Test3"
b15.ID = "a" & i
AddHandler b15.Click, AddressOf updateFunc
Panel1.Controls.Add(b15)
Next
End Sub

Find Timers by Name

Okay I'm working with visual studio and I've hit a bit of a snag. The basic situation is I have a bunch of buttons and timers that correspond to each other. For example when button1 is clicked Timer1 should start.
Currently I'm using one method to handle all of the button clicks. Which identifies the CR (1, 2, 3, etc...) and constructs a string for the name of the correct Timer that goes along with it, dim timername as string = "timer" & cr.ToString. Then when I use Me.Controls(cr).Enabled = True it returns an a null pointer error.
I know the issue has to do with the identification of the timer, suggestions?
You can't identify a control using a string (well, not easily). Try this.
Private Sub ButtonX_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click ' etc.
Dim vButton = DirectCast(sender, Button)
Select Case vButton.Name
Case "Button1"
Timer1.Start ' Or stop, or whatever
Case "Button2"
Timer2.Start
End Select
End Sub
You can also compare the button object itself using If vButton Is Button1, but that gets messy in VB (I remember having to use GetType and stuff like that).
However, if your code is as simple as my example, why not just use separate handlers for each button?!!
A Timer is a Component not a Control so it will not be located in the Control Collection. This is a case where it is probably better to not use a common button click handler since it is not simplifying anything.
However, everything which inherits from Object, such as a Button, has a Tag property which you can use to associate things with that object. In form load:
Button1.Tag = Timer1
Button2.Tag = Timer2
Button3.Tag = Timer3
Then the click event:
Private Sub ButtonX_Click(... etc ) Handles Button1.Click, Button2.Click ...
Dim thisBtn As Button = CType(sender, Button)
Dim thisTmr As Timer = Ctype(thisBtn.Tag, Timer)
thisTmr.Start
End Sub

passing variable into contextmenustrip

winforms app with 5 labels.
Each label is a variable pulled from an XML file.
I would like a right-click event to pull data into a contextmenustrip.
Right now I have it half successful. I can copy the url with a right click:
Private Sub Label1_Click(sender As Object, e As MouseEventArgs) Handles Label1.MouseClick
Dim x As String = Label1.Text
If e.Button = Windows.Forms.MouseButtons.Right Then
Dim var As String = xmlinteraction.returnLink(x)
Clipboard.SetText(var, TextDataFormat.Text)
ElseIf e.Button = Windows.Forms.MouseButtons.Left Then
xmlinteraction.appCall(x)
End If
End Sub
I would much prefer the user be prompted to see if they want to copy to clipboard, and if I can make that work I have three other menu item ideas I can easily use.
Can I could pass the copied variable into the first menu item of a contextmenustrip. So then I could create one contextmenustrip for all 5 labels and depending which label you right-click, it gives the correct value if you right-click then "Copy Link" from the contextmenustrip?
You don't need to have a separate ContentMenuStrip for each label. You can apply the one ContextMenuStrip to every label. Once you've done that you can easily determine which control it was that opened the menu from the menu's Opening event or from the Click event of the ToolStripMenuItem
For example: if you were in the Opening event and wanted to find out which Label was right-clicked on so that you could add different menu items you just need to cast the ContextMenuStrip.SourceControl property:
Label clickedLabel = (Label)contextMenuStrip.SourceControl;
Once you're in the Click event and you want to find out which Label was right-clicked on you can just do it like this:
ContextMenuStrip contextMenu = (ContextMenuStrip)((ToolStripMenuItem)sender).Owner;
Label clickedLabel = (Label)contextMenu.SourceControl;