How to get sender column and row number? - vb.net

I have a TableLayoutPanel(tlp_printing_content_layer2) with 1 column and 2 row, each cell also contain 1 button, How can i get the column and cell number when button clicked? Because i want to replace the button with another usercontrol
Private Sub btn_printer_Click(sender As Object, e As EventArgs) Handles btn_printer2.Click, btn_printer3.Click, btn_printer4.Click, btn_printer5.Click
Dim currButton As Button = sender
Dim prtp As New ctrl_PrinterPanel
currButton.Dispose()
tlp_printing_content_layer2.Controls.Add(prtp, sender.column, sender.row)
End Sub
sender.column and sender.row is not work... or is that other way to replace the button with other usercontrol?

You can iterate through the columns and rows until you find a Button matching the name of your clicked button:
Private Sub PrintButton_Click(sender As Object, e As EventArgs) Handles PrintButtonOne.Click, PrintButtonTwo.Click
'find which row was clicked
Dim rowPos As Integer = whichRow(sender, e)
'did we get a valid result?
If rowPos > -1 Then
'this is a dummy red control so that we can see it working
Dim myNewControl As Panel = New Panel With {.BackColor = Color.Red}
'remove the old
TableLayoutPanel1.Controls.Remove(DirectCast(sender, Button))
'add the new
TableLayoutPanel1.Controls.Add(myNewControl, 0, rowPos)
End If
End Sub
Private Function whichRow(sender As Object, e As EventArgs) As Integer
'cast the button that was clicked
Dim clickButton As Button = DirectCast(sender, Button)
'look through all the cols and rows
For colNum As Integer = 0 To TableLayoutPanel1.ColumnCount
For rowNum As Integer = 0 To TableLayoutPanel1.RowCount
'try cast the control we find at position colnum:rownum
Dim testcontrol As Button = TryCast(TableLayoutPanel1.GetControlFromPosition(colNum, rowNum), Button)
If Not testcontrol Is Nothing Then
'is this testcontrol the same as the click control?
If clickButton.Name = testcontrol.Name Then
Return rowNum
End If
End If
Next
Next
'not found or some other issue
Return -1
End Function

Related

Read and write below a precise cell in a CSV

I'm stuck on a basic problem. What I want is to parse through a CSV in order to compare some string and write below if I find it.
Precisely, I have a programe where I can drag and drop some button, when I drop this button I want to save it's new location on the first empty cells below the corresponding column.
Here's a sample of my CSV :
So I substring the .x/.y from my CSV and compare the name from the drop button with each cell with the help of textFieldParser. It seems to work my loop stopped when it find an equal expression.
But here's the problem I don't know how to say to my program to write below it. The first reason I can figured it out is because my parser go until the endOfData and I want it to go until the endOfDat + one row.
The second one is because I don't know if I can use a fieldwriter into textFieldParser, I mean I tried to create a variable with row+1 and write below but nothing happen when I use fileWriter.
now a sample of my code :
Private Sub manageCsv(ByVal sender As Button)
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("..\..\Pic\csvPic.csv")
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(",")
Dim currentRow As String()
Dim rowPlusOne As String()
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
rowPlusUn = MyReader.ReadFields()
Dim currentField As String
Dim str As String = btnSender.Name.Substring(3)
Dim nameDelimited As String
Dim x As Integer
For Each currentField In currentRow
''Search the corresponding field''
x = InStr(currentField, ".")
If Not (currentField.Equals("imagefile")) Then ''imagefile is the first index of my csv''
nameDelimited = currentField.Substring(0, x) ''substr the extension''
If nameDelimited.Equals(str) Then
writeCsv("..\..\Image\csvPic.csv", nameDelimited, ",")
''Ofc the "+1" does not work but that was the idea''
currentRow(+1) = lblImgName.Text
currentRow(+1) = btnSender.Location.ToString
Exit For
End If
End If
Next
Catch ex As _
Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & "is not valid and will be skipped.")
End Try
End While
End Using
End Sub
I hope it's clear enough, if not i'll try to elaborate more. Thanks for your help
Show your teacher that there are better ways to do this with a simple text file. The file will only exist if buttons have been moved before in the application. See in line comments.
Private ButtonLocation As New Dictionary(Of Button, Point)
Private MouseIsDown As Boolean
Private ptX, ptY As Integer 'Starting point of mouse relative to the button
Private btn As Button 'The button being moved
Private ButtonPath As String = "C:\Users\maryo\Desktop\Code\DroppedButtons.txt"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Reposition the buttons to where they were dropped in the previous session.
If File.Exists(ButtonPath) Then
Dim lines = File.ReadAllLines(ButtonPath) 'returns an array of strings (each line)
For Each line In lines 'loop though each line in the file
Dim fields = line.Split(","c) 'The three values on the line are separated by a comma
Dim b = DirectCast(Controls(fields(0)), Button) 'Change the string Button.Name
'to an actual Button object by finding it in the controls collection
'Set the location with the next 2 values on the line
b.Location = New Point(CInt(fields(1)), CInt(fields(2)))
'Add the Button and Location to the list
ButtonLocation.Add(b, b.Location)
Next
End If
End Sub
'These three Event procedures are the normal code to Drag and Drop a control
Private Sub Button_MouseDown(sender As Object, e As MouseEventArgs) Handles Button1.MouseDown, Button2.MouseDown
btn = DirectCast(sender, Button)
ptX = e.Location.X
ptY = e.Location.Y
MouseIsDown = True
End Sub
Private Sub Button_MouseMove(sender As Object, e As MouseEventArgs) Handles Button1.MouseMove, Button2.MouseMove
If MouseIsDown Then
'e.X and e.Y are the coordinates of the Mouse relative to the control (the Button)
'not the Form or the Screen.
btn.Location = New Point(btn.Location.X + e.X - ptX, btn.Location.Y + e.Y - ptY)
End If
End Sub
Private Sub Button_MouseUp(sender As Object, e As MouseEventArgs) Handles Button1.MouseUp, Button2.MouseUp
MouseIsDown = False
'When we drop the button with the MouseUp event we record the new location in the list
RecordButtonLocation(btn, btn.Location)
btn = Nothing
End Sub
Private Sub RecordButtonLocation(Sender As Button, Location As Point)
'Check if the Button is already in the list
If ButtonLocation.ContainsKey(Sender) Then
'Record its new location
ButtonLocation.Item(Sender) = Location
Else
'If it is not in the list add it.
ButtonLocation.Add(Sender, Location)
End If
End Sub
Private Sub Form1_Closing(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles Me.Closing
SaveDictionary()
End Sub
Private Sub SaveDictionary()
If ButtonLocation.Count > 0 Then
'If there is anything in the list we will create or overwrite the file
Dim sb As New StringBuilder
For Each kv As KeyValuePair(Of Button, Point) In ButtonLocation
sb.AppendLine($"{kv.Key.Name},{kv.Value.X},{kv.Value.Y}")
Next
File.WriteAllText(ButtonPath, sb.ToString)
End If
End Sub

Combo Box Returning -1 For SelectedIndex

I'm trying to pick up a combo box's selected index. This was working absolutely fine, then all of a sudden it started returning -1 no matter what item is selected
My code is:
Form Code
Private Sub Man_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Man.SelectedIndexChanged, Units.SelectedIndexChanged
'Set Transducer Type
Call References.LevListAdd()
End Sub
References Module LevListAdd Sub
Public Sub LevListAdd()
Form1.Lev.Items.Clear()
If Form1.Man.Text = "Pulsar" Then
With Form1.Lev.Items
.Add("Ultra Range")
.Add("IMP Range")
.Add("Twin Range")
End With
End If
End Sub
This fills the combo box lev fine when the Man combo box item "Pulsar" is selected. I then want my users to click a button to generate some labels and stuff. The code is as such:
Button Click Code
Private Sub Generate_Click(sender As Object, e As EventArgs) Handles Generate.Click
If CheckGenerate() = False Then Exit Sub
Dim X = CheckGenerationType(Man.SelectedIndex, Lev.SelectedIndex, Level.Checked, Volume.Checked, ListBox1.SelectedIndex,
Units.SelectedIndex)
Call ParamPage(X)
End Sub
CheckGenerate simply checks that all boxes have been filled in. I pass the informtion from the form to the following function:
Public Function CheckGenerationType(Man As Integer, Lev As Integer, Level As Boolean, Volume As Boolean, TankType As Integer,
MeasurementUnit As Integer) As String
Dim M As Integer
Dim L As Integer
Dim CT As Integer
Dim TT As Integer
Dim Ms As Integer
M = Man
L = Lev
TT = TankType
Ms = MeasurementUnit
If Level = True Then
CT = 0
ElseIf Volume = True Then
CT = 1
End If
CheckGenerationType = CStr(M) + "." + CStr(L) + "." + CStr(CT) + "." + CStr(TT) + "." + CStr(Ms)
End Function
When the lev.selectedindex parameter arrives at this function, it reads -1. Even if the user has selected any of the 3 items. Can anyone explain why this is happening?
I've just tried your code. I get the same result (-1 in lev.SelectedIndex) and this was because jumped using tab through the controls my when i'm hitting the Man or Units Combobox it runs the LevListAdd() and then clears the Lev-ComboBox because of Form1.Lev.Items.Clear().
You should think about your call Man_SelectedIndexChanged_1 or maybe just use something like this:
Public Sub LevListAdd()
If Form1.Man.Text = "Pulsar" Then
Form1.Lev.Items.Clear()
instead of
Public Sub LevListAdd()
Form1.Lev.Items.Clear()
If Form1.Man.Text = "Pulsar" Then
And you should separate the calls from the man and unit ComboBoxes.
Private Sub Unit_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Units.SelectedIndexChanged
' Do something
End Sub
Private Sub Man_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Man.SelectedIndexChanged
Form1.Lev.Items.Clear()
Select Case Form1.Man.Text
Case "Pulsar"
With Form1.Lev.Items
.Add("Ultra Range")
.Add("IMP Range")
.Add("Twin Range")
End With
Case "animals"
With Form1.Lev.Items
.Add("dogs")
.Add("cats")
.Add("birds")
End With
End Select
End Sub

detect when left mouse button is down while hovering over a button in Visual Basic.net

So I'm attempting to create a schedule grid in VB.net (exactly like the scheduler in UTorrent, if anyone is familiar) in a 24x7 layout. I want to be able to click down and drag over a series of squares to change the values of them.
I've been able to find this sample code that mostly works.
Private Sub DataGridView3_MouseHover(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DataGridView3.CellMouseMove
Dim grvScreenLocation As Point = DataGridView3.PointToScreen(DataGridView3.Location)
Dim tempX As Integer = DataGridView.MousePosition.X - grvScreenLocation.X + DataGridView3.Left
Dim tempY As Integer = DataGridView.MousePosition.Y - grvScreenLocation.Y + DataGridView3.Top
Dim hit As DataGridView.HitTestInfo = DataGridView3.HitTest(tempX, tempY)
cellX = hit.RowIndex
cellY = hit.ColumnIndex
TextBox3.Text = cellX
TextBox14.Text = cellY
End Sub
As written, this produces the desired results, however I need to have it only return cellx and celly to the text boxes only when the mouse button is down.
This can be accomplished by handling mouse left button down, mouse move and mouse left button up.
When you receive a mouse left button down event on the grid, record the mouse position and set a flag. In the mouse move handler if the flag is set, highlight all cells between the initial position and the current mouse position. On receiving a mouse left button up (on the grid when the grid is set) commit the cell selection (and clear the flag).
I've used this technique successfully for a fractal zoom.
Here's a rough outline of what you need to do:
Dim isSelecting As Boolean
Dim selectionStart As Point
Protected Overrides Sub OnMouseLeftButtonDown(e As MouseButtonEventArgs)
MyBase.OnMouseLeftButtonDown(e)
Dim position = e.GetPosition(Me)
Dim hit = VisualTreeHelper.HitTest(MyGrid, position)
If hit IsNot Nothing Then
isSelecting = True
selectionStart = position
End If
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
If isSelecting Then
Dim position = e.GetPosition(Me)
' Update selection
End If
End Sub
Protected Overrides Sub OnMouseLeftButtonUp(e As MouseButtonEventArgs)
MyBase.OnMouseLeftButtonUp(e)
If isSelecting Then
Dim position = e.GetPosition(Me)
' Commit selection
End If
End Sub
This gave me what I wanted.
Private cellX As Integer = 0
Private cellY As Integer = 0
Private Sub DataGridView3_MouseHover(ByVal sender As System.Object, ByVal e As MouseEventArgs) Handles DataGridView3.CellMouseMove
Dim grvScreenLocation As Point = DataGridView3.PointToScreen(DataGridView3.Location)
Dim tempX As Integer = DataGridView.MousePosition.X - grvScreenLocation.X + DataGridView3.Left
Dim tempY As Integer = DataGridView.MousePosition.Y - grvScreenLocation.Y + DataGridView3.Top
Dim hit As DataGridView.HitTestInfo = DataGridView3.HitTest(tempX, tempY)
cellX = hit.RowIndex
cellY = hit.ColumnIndex
If e.Button = Windows.Forms.MouseButtons.Left Then
TextBoxX.Text = cellX
TextBoxY.Text = cellY
DataGridView3.Rows(cellX).Cells(cellY).Style.BackColor = Color.Red
End If
End Sub

VB.Net: Using and addressing buttons in TableLayoutPanel

Hi I have this TablelayoutPanel setup currently in my program to create a grid of buttons that will later correspond to a specific column and row:
'****INITIALISES TABLE LAYOUT INTO FORM******
Dim ColCount, RowCount As Integer
'Later change so that values are automatically calculated
ColCount = 5
RowCount = 5
'*********Copy and pasted from site as example, CHANGE LATER*******
Haztable = New TableLayoutPanel
Haztable.AutoScroll = True
Haztable.Dock = DockStyle.Fill
Haztable.ColumnCount = ColCount
Haztable.RowCount = RowCount
For rowNo As Integer = 0 To Haztable.RowCount - 1
For columnNo As Integer = 0 To Haztable.ColumnCount - 1
'Dim ctrl As Control = New Button
'ctrl.Text = String.Format("{0} {1},{2}", ctrl.GetType().Name, columnNo, rowNo)
'ctrl.Size = New Size(20, 20)
'Haztable.Controls.Add(ctrl, columnNo, rowNo)
Dim buttonname As String
buttonname = "B" & columnNo & rowNo
Dim button As Control = New Button
button.Size = New Size(70, 20)
button.Name = buttonname
button.Text = buttonname
Haztable.Controls.Add(button, columnNo, rowNo)
AddHandler button.Click, AddressOf buttonname_Click
Next
Next
Me.Controls.Add(Haztable)
Call buttonfind()
And this all works, creating a grid of buttons, much like the layout of an excel spreadsheet.
The buttons are named according to their XY position (e.g. the button in (1,1) would be called "B11") but the problem is I can't seem to work out how I can address these buttons i.e
*If B(X.Y) is clicked then save boolean value that button at X,Y is pressed.
It would be great to have one algorithm to scan and check if any buttons have been pressed instead of using "Select Case" for each button.
I would just create the buttons in the designer but for my full code i'm going to need 1000+ buttons and that seems an inefficient way to do so.
Your buttonname_Click should have a Sender object which is the Button that you Clicked just cast it to a Button and check the name then.
Private Sub buttonname_Click(sender As System.Object, e As System.EventArgs)
Dim btn As Button = CType(sender, Button)
Select Case btn.Name
Case "B11"
'Do something
Case "B12"
'Do Something esle
'...........
End Select
End Sub
Based on your last statement see if this works you may need to build an Array or a List if you need to reference the Text elsewhere in your Program
Private Sub buttonname_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim btn As Button = CType(sender, Button)
If btn.Text = "H" Then
btn.Text = "M"
ElseIf btn.Text = "M" Then
btn.Text = "L"
ElseIf btn.Text = "L" Then
btn.Text = ""
Else
btn.Text = "H"
End If
End Sub
You have add clicked event and handle each of them by using their row and column number. Make yourself a new button first so that you can access row and column numbers with spending no effort to parse column and row numbers from the controls name:
Public Class NewButton
Inherits Button
Public Row, Column, ClickCount as Integer
End Class
Now create and handle:
Public Class Form1
Sub addbuttons()
Dim newbut As New NewButton
newbut.Name = "B12"
newbut.Row = "1"
newbut.Column = "2"
'and other properties...
AddHandler newbut.Click, AddressOf clicked
Me.Controls.Add(newbut)
End Sub
Sub clicked(sender As System.Object, e As System.EventArgs)
Dim x As NewButton = DirectCast(sender, NewButton)
If x.Column = 2 And x.Row = 1 Then
x.ClickCount += 1
End If
End Sub
End Class

How to loop through each button to check if they are enabled or not?

I want to do a For Each loop where i can check whether each button is enabled or disabled. If the button is enabled then i have to obtain the values in the tags for each button. I have 26 buttons each containing different values (cash prizes).*IMPORTANT: this code needs to go under the button so every sixth time its pressed it checks the buttons.
Pseudo-Code:
btncase1.tag = 5
Begin while statement to go through each button
Check each button to see if it is enabled
If button is enabled then obtain values
Next
Actual code i have but it doesnt make any sense to me:
Public Class Form1
Dim button As Button
Dim totalremcases As Integer
Dim btncase As New Control
Dim btncollection As New Microsoft.VisualBasic.Collection()
Private Sub btncase1_Click()
For Each button As Button In btncollection
If btncase.Enabled Then
totalremcases = totalremcases + CInt(btncase.Tag)
End If
Next
you can try to solve it by using this approach
Public Sub getallcontrolls(controls As System.Web.UI.ControlCollection)
Dim myAL As New ArrayList()
For Each ctrl As Control In controls
If TypeOf ctrl Is Button Then
If ctrl.Enabled = True Then
Dim tag As String = ctrl.Tag.ToString()
myAL.Add(tag)
End If
End If
Next
End Sub
It seem that you are making a "Deal or No Deal" kind of game.
You can create a button click counter (form level variable) so that you can keep track of how many buttons are clicked already. Increment the counter every time a button is clicked.
Create a function to accumulate values of the tags. You call this function only if the counter is divisible by 6. (You said you check every sixth time a button is pressed)
Dim counter As Integer
Dim total As Integer
Private Function AccumulateTags() As Integer
Dim ctl As Control
Dim total As Integer
For Each ctl In Me.Controls
If TypeOf ctl Is Button Then
If ctl.Enabled = True Then
total += Val(ctl.Tag)
End If
End If
Next
Return total
End Function
Private Function disable(sender As Object)
Dim ctl As Control
For Each ctl In Me.Controls
If TypeOf ctl Is Button AndAlso sender.Equals(ctl) Then
ctl.Enabled = False
End If
Next
End Function
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click, _
Button2.Click, Button3.Click, Button4.Click, Button5.Click, Button6.Click, Button7.Click
counter += 1
If counter Mod 6 = 0 Then 'Checks if counter is divisible by 6
total = AccumulateTags()
End If
MsgBox("Total" & total) 'Displays total. You may also display it in a label if you want
disable(sender)
End Sub