Changing the text of all the buttons on a form in VB.net - vb.net

Call me crazy but for the life of me I cannot make this work. I have the following code:
Dim cControl As Control
For Each cControl In Me.Controls
If (TypeOf cControl Is Button) Then
cControl.ForeColor = Color.Black
cControl.Font = New Font(cControl.Font, FontStyle.Regular)
End If
Next cControl
Me.ActiveControl.ForeColor = Color.Blue
Me.ActiveControl.Font = New Font(Me.ActiveControl.Font, FontStyle.Bold)
I am trying to make the font black and regular for all of the buttons on the form (there are a lot) and the button just clicked, bolded and blue.
The second part of the code works (making the font bold and blue), it's the first that is not simply working.
What am I missing?

I've never tried it like that before, but I have used Linq to accomplish what you want.
Dim btn() As Button
btn = Me.Controls.OfType(Of Button)().Where(Function(c) c.Name.Contains("")).ToArray()
This will basically create an array of buttons from your form, then you can just loop through each one.
Dim i As Integer = 0
While i < btn.Count
btn(i).Enabled = True
btnText(i).BackColor = Color.DarkOliveGreen
btnText(i).ForeColor = Color.White
i += 1
End While
If you have a naming convention for your buttons and want to only change certain buttons where the empty quotes are you can have "btnTest".
Then you will have an index of any button that contains the text "btnTest" in it. So that would include "btnTest1", "btnTest2", "btnTestAnything1234" etc.
Hope this helps and you can use it!

Nevermind I found my problem. The buttons are in a group box so I had to reference the group box directly

Related

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.

How to terminate the last action when a new label is clicked?

I have many labels. When a label is clicked, I change the BackColor to aqua. When I click on another label, both of them are aqua, but I want the color of the first label to go back to normal. It there a way to do that?
Here is my code:
Dim clickedLabel = TryCast(sender, Label)
If clickedLabel IsNot Nothing Then
clickedLabel.BackColor = Color.Aqua
TextBox1.Text = clickedLabel.Text
Else
End If
Put them all in a collection so that you can apply the default-color on all others or - if they are all in the same container-control like a Panel - use this code:
For Each lbl In LabelPanel.Controls.OfType(Of Label)()
clickedLabel.BackColor = If(lbl Is clickedLabel, Color.Aqua, DefaultColor)
Next
TextBox1.Text = clickedLabel.Text
Instead of LabelPanel.Controls you could also use Me.Controls, but then all labels on the form are used even if it's not related. Labels that are in other container controls won't be find in this way anyway, so no recursive search.
DefaultColor is a System.Drawing.Color that you store as class/member variable(shared or as instance-variable).

VB.Net 2008 Buttons acts as Tab Controls

I am looking for a way to design things differently in my project. Instead of using TabControls I wish to use Buttons (Instead of pressing the tabs on the top I would like to press the Buttons on the left-side). These buttons when pressed they have their own Panel where each has their own respective content.
Select Case tabAdmin.SelectedIndex
Case 0
If txtCode_Patient.Text = "" Then
txtCode_Patient.Focus()
Else
cmdAdminister.Focus()
End If
Case 1
If txtD_Patient.Text = "" Then
txtD_Patient.Focus()
Else
cmdRefresh.Focus()
End If
Case 2
If txtI_Patient.Text = "" Then
txtI_Patient.Focus()
Else
cmdI_CUser.Focus()
End If
Case 3
If txtStat_CS.Text = "" Then
txtStat_CS.Focus()
Else
cmdStat_Refresh.Focus()
End If
End Select
The code above is similar to what my project acts and it works with TabControls. I want to do a similar thing but this time, like I said before, pressing Buttons on the left-side. How can I do a similar thing ?
UPDATE:
I found a way for this one but now my concern is how do I make it look like one of its default button 3D look-alike?
Public Class Tab
Inherits TabControl
Private Property DoubledBuffered As Boolean
Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)
DoubledBuffered = True
SizeMode = TabSizeMode.Fixed
ItemSize = New Size(30, 110)
End Sub
Protected Overrides Sub CreateHandle()
MyBase.CreateHandle()
Alignment = TabAlignment.Left
End Sub
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
Dim B As New Bitmap(Width, Height)
Dim G As Graphics = Graphics.FromImage(B)
G.Clear(Color.AliceBlue)
For i = 0 To TabCount - 1
Dim TabRectangle As Rectangle = GetTabRect(i)
If i = SelectedIndex Then
'//Selected
G.FillRectangle(Brushes.DarkSlateGray, TabRectangle)
Else
'//Not Selected
G.FillRectangle(Brushes.AntiqueWhite, TabRectangle)
End If
G.DrawString(TabPages(i).Text, Font, Brushes.Black, TabRectangle, New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
Next
e.Graphics.DrawImage(B.Clone, 0, 0)
G.Dispose() : B.Dispose()
MyBase.OnPaint(e)
End Sub
End Class
Use the CheckBox control instead of Button, but set Appearance = Button, that way it looks exactly like a button can remains in the "pressed" state when clicked.
To shift between content, put each of your sub-forms into their own UserControl instances, then host them within a Panel control, then switch the .Visibility property of each sub-form according to which CheckBox was clicked.
There is an Outlook-style side bar available on Code Project. It has a VB version as well as C# and although it's knocking on a bit now, you could always adapt this to look a bit nicer. I have used it in the past and it worked pretty well as I recall.
You can set the selected tab via tabAdmin.SelectedIndex = 0 (or 1, 2, etc, but remember it is 0 based)
You may also set the tab by the tab's name via tabAdmin.SelectedTab = TabName
Use a common click event handler for the buttons. Store the relevant tabindex in the Tag property of the buttons. Then tabAdmin.SelectedIndex equals the tag of the clicked button cast as integer.

Order of controls being added to panel, control not showing unless docked

I imagine this is probably an easy to answer question but for some reason I can't get it to work
Sub New(ByVal Sess As AudioSessionControl2)
S_Session = Sess
'Create the panel and position it.
S_Panel.BackColor = Color.AliceBlue
S_Panel.Width = 200
S_Panel.Height = 40
Dim Position As New Point(6, 19)
If G_AppSessions.Count > 0 Then
Position = Point.Add(G_AppSessions.Item(G_AppSessions.Count - 1).SessionPanel.Location, New Point(0, 45))
End If
S_Panel.Location = Position
'Create a label which has the name of the process
Dim S_PName As New Label
S_PName.Text = "Test"
S_PName.Dock = DockStyle.Left
S_Panel.Controls.Add(S_PName)
'Create a button to change volume
Dim S_Save As New Button()
S_Save.Text = "Save"
AddHandler S_Save.Click, AddressOf Save_Click
S_Save.Parent = S_Panel
S_Panel.Controls.Add(S_Save)
S_Volume.Parent = S_Panel
S_PName.Parent = S_Panel
MainForm.Controls.Add(S_Panel)
S_Panel.Parent = MainForm.gb_Applications
End Sub
The problem is that, the label will show because its docked, but the button won't. It will only show if its docked as well, and thats just not what I want. This is part of a class for creating a dynamic UI, where I can create a number of this class to create a bunch of panels for various things.
I don't see anywhere where you are setting the label or button position. You probably have them both at 0,0 and the label is on top of the button, obscuring it. Did you try setting the position of both the controls, making sure they don't overlap?

Looping through Controls in VB.NET

I am creating a chess program. And it is composed of sixty four picture boxes with alternating black and white background colours.
I have named them pba1, pba2, pbb1, pbb2, pbc1 and so on.
Now, I want to loop through only the black ones, for example, I want to loop through only, pba1, pbb2, pbc3 and so on.
How do I create a loop for this in VB.NET?
I know of the way to loop through similarly named controls, but I am not able to adapt that method for my problem. Can you tell me a solution?
EDIT: In pba1, pb stands for picture box, and a1 stands for the square. Just in case, you wonder why such a name.
EDIT: Check out this answer
Loop through the PictureBox's in your ControlCollection and test for BackColor. I used the Form's ControlCollection, if they are in some other type of container control use that.
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is PictureBox Then
If cntrl.BackColor = Color.Black Then
'Do Something
End If
End If
Next
Base on the additional information that you gave in your answer, the reason your example is not working is that the Controls Name is a String and you are comparing it to the PictureBox Control not the Name of the Control.
You can try using the Tag Property instead of the Name of the Control, it will be cleaner and easier to read. I just put a 1 in the PictureBox's Tag Property for Black and a 0 for White.
Private Sub OriginalColour()
For Each cntrl As Control In Me.Controls
Dim result As Integer
If TypeOf cntrl Is PictureBox Then
If Integer.TryParse(cntrl.Tag.ToString, result) Then
If result = 1 Then
cntrl.BackColor = Color.Gray
Else
cntrl.BackColor = Color.White
End If
End If
End If
Next
End Sub
Generating controls at design time via the Forms Designer only makes sense for layouts which benefit from the forms designer.
In your case, you just have 64 uniform boxes in 8 rows of 8. Don’t use the Forms Designer for this, create the controls at runtime, and don’t give them names like pba1, just put them into an appropriate data structure (such as an 8x8 array):
Private chessFields As PictureBox(8, 8)
' In Form_Load:
For i = 0 To 7
For j = 0 To 7
chessFields(i, j) = New PictureBox
' Set size, position … then, finally,
Controls.Add(chessFields(i, j))
Next
Next
That way, you can access the fields in an orderly fashion without having to go via the Form.Controls collection.
Put all the pictureboxes in an 8x8 tableLayoutPanel (also useful for scaling etc). Then
For Each pb As PictureBox In TableLayoutPanel1.Controls
Dim col As Integer = TableLayoutPanel1.GetCellPosition(pb).Column
Dim row As Integer = TableLayoutPanel1.GetCellPosition(pb).Row
If col Mod 2 = 0 Xor row Mod 2 = 0 Then
pb.BackColor = Color.Black
Else
pb.BackColor = Color.White
End If
Next
Of course you could also use an array of the squares if you have that available.
This will not affect the events (pba1.click etc).
This is fairly simple and it may be resource heavy, but it works. I have a form with 36 CheckBoxes. This takes advantage of the fact that when you copy a checkbox it just increases the number of the name. I ended up with 36 checkboxes named CheckBox1 thru Checkbox36. The Function returns a checkbox, which may be used to set or read any property.
Private Function GetCheckBox(ByVal Index As Integer) As CheckBox
Dim CKBox As checkbox
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is CheckBox Then
CKBox = cntrl
If CKBox.Name = "CheckBox" & Index Then
Exit For
End If
End If
Next
Return ckbox
End Function