Visual Basic: reference label control from variable derived from checkbox control - vb.net

I'm writing a simple Windows Form app in VB using VS Community 2017.
I have 64 checkboxes with 64 associated labels, named chk1 / lbl1 up to chk64 / lbl64. When a checkbox is checked, I want to extract a character from a string and show the answer in the label: e.g. if chk12 is checked, I want lbl12 to be enabled and the text to display the 12th character of the string.
To save writing 64 separate handlers I'm trying to do it in one. I can extract the checked number (e.g. 12) OK and write it to a string, but when I try to manipulate the label control I get an 'Object reference not set to an instance of an object' error.
The code I've come up with so far (largely from searching in here) is:
Private Sub CheckedChanged(sender As Object, e As EventArgs) _
Handles chk1.CheckedChanged, chk2.CheckedChanged 'etc. to 64
' wanted behaviour
'If chk1.Checked Then
' lbl1.Enabled = True
' lbl1.Text = GetChar(userString, 1)
'End If
'If chk2Checked Then
' lbl2.Enabled = True
' lbl2.Text = GetChar(userString, 2)
'End If
' etc. (to 64)
Dim resultsLabel As String
Dim userCheckedBox As Integer
userCheckedBox = CInt(DirectCast(sender, CheckBox).Text)
resultsLabel = "lbl" & DirectCast(sender, CheckBox).Text
Me.Controls(resultsLabel).Enabled = True
Me.Controls(resultsLabel).Text = GetChar(userString, userCheckedBox)
End Sub
I'd be very grateful if someone can nudge me over the line with this. Many thanks!

There is the old trick to use the Tag property of your checkboxes.
You can set the Tag property to the matching label name at design time using the WinForms Designer. So in the chk1.Tag property you will have the "lbl1" string assigned and so on for all the 64 checkboxes.
At this point your code in the event handler is simply
Dim chk = DirectCast(sender, CheckBox)
if chk IsNot Nothing Then
Me.Controls(chk.Tag.ToString()).Enabled = True
Me.Controls(chk.Tag.ToString()).Text = GetChar(userString, CInt(chk.Text))
End If

Related

VS 2022 project is missing the x64 option, only has Any CPU as option

I am at my wits end. I have a VS 2022 VB Winforms application that was working perfectly fine up until last night. Now I am getting numerous errors, most of which state "Value of type 'ComboBox()' cannot be converted to 'ComboBox()' because 'ComboBox' is not derived from 'ComboBox'". Another error staes "'DropDownWidth' is not a member of 'ComboBox'". The only thing I noticed is that the solution platform now reads "Any CPU" instead of "x64". I did not change any code that has to do with the combobox routines so the errors seemed to have come out of nowhere and the x64 solution platform is no longer an option. Any ideas? I included my code where the errors started popping up.
Public Class GlobalVar
Public Shared cmbBurgType() As ComboBox = {frmSearchNOC.cmbSearchBurgType, frmAddEntry.cmbAddBurgType}
Public Shared cmbSex() As ComboBox = {frmSearchNOC.cmbSearchSex, frmAddEntry.cmbAddSex}
Public Shared cmbRace() As ComboBox = {frmSearchNOC.cmbSearchRace, frmAddEntry.cmbAddRace}
Public Shared cmbPrefix() As ComboBox = {frmSearchNOC.cmbSearchHomeStreetPrefix, frmAddEntry.cmbAddHAddressPrefix}
Public Shared cmbSuffix() As ComboBox = {frmSearchNOC.cmbSearchHomeStreetSuffix, frmAddEntry.cmbAddHAddressSuffix}
Public Shared cmbState() As ComboBox = {frmSearchNOC.cmbSearchHomeState, frmAddEntry.cmbAddHAddressState}
Public Shared cmbPrecinct() As ComboBox = {frmSearchNOC.cmbSearchHomePrecinct, frmAddEntry.cmbAddHAddressPrecinct}
Public Shared cmbTattooLoc() As ComboBox = {frmSearchNOC.cmbSearchTattooLocation, frmAddEntry.cmbAddTattoo}
End Class
Public Sub LoadPresetDBDataCombobox(tableName As String, colName As String, objArray() As ComboBox)
Dim longestEntry As String = ""
Dim curText As String = ""
Dim sqliteReader As SQLiteDataReader
Dim sqliteReadCmd As SQLiteCommand
'clear combobox items
For Each curBox As ComboBox In objArray
curBox.Items.Clear()
Next
OpenDBConn() 'opens the database connection
sqliteReadCmd = GlobalVar.dbConn.CreateCommand()
sqliteReadCmd.CommandText = "Select " & colName & " FROM " & tableName
sqliteReader = sqliteReadCmd.ExecuteReader()
sqliteReadCmd.Dispose() 'disposes read command after it is used
'iterate through table
Using sqliteReader
While sqliteReader.Read
curText = sqliteReader.GetString(colName) 'gets the current table value for the selcted column
'places value into each combobox in array
For Each curBox As ComboBox In objArray
curBox.Items.Add(curText)
Next
'determines the length of the longest string to size to properly dize the drop down width to fit text
If (curText.Length > longestEntry.Length) Then
longestEntry = curText
End If
End While
'assigns the dropdownwidth based on an everage character width of 6 pixels
For Each curBox As ComboBox In objArray
curBox.DropDownWidth = ((longestEntry.Length * 7) + 10)
Next
sqliteReader.Close() 'close object
longestEntry = ""
End Using
CloseDBConn() 'closes the database connection
End Sub
Private Sub OpenChildForm(childForm As Form, formIndex As Integer)
If (currentChildForm IsNot Nothing) Then
currentChildForm.SendToBack()
End If
currentChildForm = childForm 'assigns passed in form as current form
childForm.TopLevel = False 'indicated the form is not top level because the main form is top level
childForm.Dock = DockStyle.Fill 'docks form to fill main form's panel
pnlMain.Controls.Add(childForm) 'adds form to the main panel on the main form
pnlMain.Tag = childForm 'associate form to main panel on main form
childForm.BringToFront() 'brings the related form to the front
childForm.Show()
Select Case formIndex
Case 0 'search noc form
'reloads various data from db into comboboxes in case items were added while on another tab
LoadPresetDBDataCombobox("BurgType", "typeName", GlobalVar.cmbBurgType) 'tattoo location
LoadPresetDBDataCombobox("Sex", "sexName", GlobalVar.cmbSex) 'sex
LoadPresetDBDataCombobox("Race", "raceName", GlobalVar.cmbRace) 'race
LoadPresetDBDataCombobox("StreetPrefix", "prefixName", GlobalVar.cmbPrefix) 'street prefix
LoadPresetDBDataCombobox("StreetSuffix", "suffixName", GlobalVar.cmbSuffix) 'street suffix
LoadPresetDBDataCombobox("State", "stateName", GlobalVar.cmbState) 'state
LoadPresetDBDataCombobox("Precinct", "precinctName", GlobalVar.cmbPrecinct) 'home precinct
LoadPresetDBDataCombobox("BodyPart", "bodyPartName", GlobalVar.cmbTattooLoc) 'tattoo location
Case 1 'browse results form
Case 2 'add entry form
'reloads various data from db into comboboxes in case items were added while on another tab
LoadPresetDBDataCombobox("BurgType", "typeName", GlobalVar.cmbBurgType) 'tattoo location
LoadPresetDBDataCombobox("Sex", "sexName", GlobalVar.cmbSex) 'sex
LoadPresetDBDataCombobox("Race", "raceName", GlobalVar.cmbRace) 'race
LoadPresetDBDataCombobox("StreetPrefix", "prefixName", GlobalVar.cmbPrefix) 'street prefix
LoadPresetDBDataCombobox("StreetSuffix", "suffixName", GlobalVar.cmbSuffix) 'street suffix
LoadPresetDBDataCombobox("State", "stateName", GlobalVar.cmbState) 'state
LoadPresetDBDataCombobox("Precinct", "precinctName", GlobalVar.cmbPrecinct) 'home precinct
LoadPresetDBDataCombobox("BodyPart", "bodyPartName", GlobalVar.cmbTattooLoc) 'tattoo location
Case 3'user settings form
Case 4 'administrator form
End Select
End Sub
Above, the errors come into play with all the GlobalVar parameters as well as the dropdownwidth call:
LoadPresetDBDataCombobox("StreetPrefix", "prefixName", GlobalVar.cmbPrefix)
curBox.DropDownWidth = ((longestEntry.Length * 7) + 10)
I tried updating VS 2022 and then reinstalled it. Neither of which worked, obviously, considering I'm asking this question. It's probably something simple and stupid but I am fried and could use some help.
Thanks to anyone who spent time reading my question. I have no idea how or when the following import got added to one of my routines but I commented it out and all the errors went away:
Imports System.Windows.Controls
I noticed it when I was copying code from my broken project to a new project to see when the errors start popping up. My best guess is that it was importing a combobox control that was different from the combobox I was trying to pass into the routine, but any comments that explain the reason are appreciated.

VB.NET 2019 How to populate a Tag Property on a dynamic ToolstripmenuItem

I am struggling to populate a tag property on a dynamically created sub menu which I have created. I have a text file that contains a number of radio station names, BBC1, BBC2, BBC3 for example, as well as the associated stream addresses for said stations. I am able to pull in the names and apply it to the submenu. They appear fine. I can click on the submenus, and the sender() variable confirms the station names correctly. My problem is that I cannot get the Tag property for each sub menu/radio station, to store the stream address. The code gets the radio title cleans the code and inserts it into the RadioStreamsToolStripMenuItem.DropDownItems.Add(station_name) and all is fine. The code then gets the Stream address and inserts it here RadioStreamsToolStripMenuItem.Tag.ToString(). I can tell that it is wrong, but how do I go about ensuring the correct stream goes into the correct radio Tag property. Im very new to this so please be gentle, its just a little hobby.
'======================================================================
'Aquires Radio name and creates a dropdown sub menu within RadioStreams
'======================================================================
Do While (Not line Is Nothing)
If line.StartsWith("#") Then
station_name = Replace(line, "#", "")
Dim x = RadioStreamsToolStripMenuItem.DropDownItems.Add(station_name)
AddHandler x.Click, AddressOf ToolMenuItem_Click
'===================================================
'Aquires Radio Stream to add to the Tag property for each new station
'===================================================
ElseIf line.StartsWith("#") Then
Dim station_stream As String = Replace(line, "#", "")
'The following just checks if the data has gone into the correct place
For Each Myitem As ToolStripItem In RadioStreamsToolStripMenuItem.DropDownItems
If Myitem.Text = station_name Then
MsgBox("MyItems " & Myitem.ToString())
Me.Tag = station_stream
End If
Next
You could use a Dictionary to store the stations a stream addresses. Dictionary lookups are very fast.
I assumed from your code that your text file looks like this
#BBC1
#BBC1streamAddress
#BBC2
#BBC2streamAddress
#BBC3
#BBC3streamAddress
I looped through the lines of the file assigning the trimmed keys and values to the dictionary. Then looped through the dictionary filling the menu. When the user clicks a menu item we get the text of the item and search the dictionary for the correct stream address.
Private RadioDictionary As New Dictionary(Of String, String)
Private Sub OPCode()
Dim lines = File.ReadAllLines("Radio.txt")
For i = 0 To lines.Length - 1 Step 2
RadioDictionary.Add(lines(i).Trim("#"c), lines(i + 1).Trim("#"c))
Next
For Each item In RadioDictionary
Dim x = RadioStreamsToolStripMenuItem.DropDownItems.Add(item.Key)
AddHandler x.Click, AddressOf ToolMenuItem_Click
Next
End Sub
Private Sub ToolMenuItem_Click(sender As Object, e As EventArgs) Handles ToolMenuItem.Click
Dim station = DirectCast(sender, ToolStripDropDownItem).Text
Dim stream = RadioDictionary(station)
End Sub

Change Font Style on All Instances of a String in a RichTextBox

I'm working on a VB.NET 4.5 project in VS2013.
I have a richtextbox on a form and when a button is clicked I need to toggle the BOLD setting on all instances of a specific string found in the richtextbox.
I put together some code based on this question.
Private Sub ToggleBold()
rtxtOutputText.SelectionStart = rtxtOutputText.Find("##$%", RichTextBoxFinds.None)
rtxtOutputText.SelectionFont = New Font(rtxtOutputText.Font, FontStyle.Bold)
End Sub
However when the toggle bold button is clicked it only bolds the first instance of the string "##$%".
How can I set all instances of the string to bold? There can also be several of them strung together ("##$%##$%##$%"), so each of those would need to be bolded too.
(I know I mentioned toggling bold, but I'll set up the toggle portion later, right now I'm just trying to get the bold on all instances working right...)
Just add a loop to it and use the RichTextBox.Find(String, Int32, RichTextBoxFinds) overload to specify from where to start looking. Look from the current index + 1 so that it doesn't return the same again.
You also ought to actually select the word as well, so that you're sure the bold applies to the current instance only and not the text around it.
Private Sub ToggleBold()
'Stop the control from redrawing itself while we process it.
rtxtOutputText.SuspendLayout()
Dim LookFor As String = "##$%"
Dim PreviousPosition As Integer = rtxtOutputText.SelectionStart
Dim PreviousSelection As Integer = rtxtOutputText.SelectionLength
Dim SelectionIndex As Integer = -1
Using BoldFont As New Font(rtxtOutputText.Font, FontStyle.Bold)
While True
SelectionIndex = rtxtOutputText.Find(LookFor, SelectionIndex + 1, RichTextBoxFinds.None)
If SelectionIndex < 0 Then Exit While 'No more matches found.
rtxtOutputText.SelectionStart = SelectionIndex
rtxtOutputText.SelectionLength = LookFor.Length
rtxtOutputText.SelectionFont = BoldFont
End While
End Using
'Allow the control to redraw itself again.
rtxtOutputText.ResumeLayout()
'Restore the previous selection.
rtxtOutputText.SelectionStart = PreviousPosition
rtxtOutputText.SelectionLength = PreviousSelection
End Sub
Credit to Plutonix for telling me to dispose the font.

Call form controls' properties in a function

I want to create a function that receives forms as an input. I need to use controls' properties of the passed form. For example:
Private Sub Drawing(ByVal frm As Form)
X = frm.a.Left + frm.a.Width
End Sub
Visual basic doesn't accept this method that I use. How can I solve it?
The code should be like this :
Private Sub Drawing(ByVal frm As Form)
Dim i As Control()
i = frm.Controls.Find("a", True)
if i.Length <> 0 Then
X = i(0).Left + i(0).Right
End If
End Sub
"Visual Basic doesn't accept this method that I use" is a very vague description of your problem. You should be specific with what errors you get and what you want the result to be, because we are not mindreaders and can therefore not tell what the problem is unless we get clear information.
But if you're trying to change a control's/form's X-position you have to change the entire Location property.
Change the current form's X-position:
Me.Location = New Point(frm.a.Left + frm.a.Width, Me.Location.Y)
Change a control's X-position (where YourControl is the name of the control you want to move):
YourControl.Location = New Point(frm.a.Left + frm.a.Width, YourControl.Location.Y)

Access a dynamically created textbox text from another sub. And I also want to be user-configurable and access the user-configured text

Textbox.text I want to access. And I want it user-configurable before I want to access the altered text.
Dim qbox As New TextBox
qbox.Size = New Size(20, 20)
qbox.Location = New Point(90, 10)
qbox.Parent = addtocart
qbox.Name = "quarts"
qbox.Text = "ss"**
how I dynamically add it inside a series of other dynamic controls:
tile.Controls.Add(addtocart)
flpp.Controls.Add(tile)
tile.Controls.Add(plabel)
tile.Controls.Add(nlabel)
addtocart.Controls.Add(qbox)
How I tried to access it:
qb.Text = CType(Me.Controls("flpp").Controls("tile").Controls("addtocart").Controls("qbox"), TextBox).Text
I generated to textbox at runtime. Of course it's dynamic. I'm new to VB and I'm just experimenting a school project. I wanted the textbox text to be configurable and then access that configured value. I've been brain-cracking for days about this. when I run the thing, I "getObject reference not set to an instance of an object." under NullReferenceException was unhandled" something like this. I don't get it.
WinForms? If yes, and you want to find that control "by name", then use the Controls.Find() function:
Dim ctlName As String = "quarts"
Dim matches() As Control = Me.Controls.Find(ctlName, True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is TextBox Then
Dim tb As TextBox = DirectCast(matches(0), TextBox)
' ... use "tb" somehow ...
Dim value As String = tb.Text
MessageBox.Show(value)
End If