Changed checked state on checkbox with button appearance in VB.NET - vb.net

As stated in my summary, I am currently working on a Virtual OS in VB.Net. I am currently working on the session as I am done with the login stuff.
I am having trouble with a checkbox with button appearance. I want to set the CheckState to Checked if I click on the button with the Click() event like this:
Private Sub btnApps_Click(Byval sender As Object, Byval e As EventArgs) Handles btnApps.Click()
If btnApps.CheckState = CheckState.Checked Then
btnApps.CheckState = CheckState.Unchecked
Else
btnApps.CheckState = CheckState.Checked
End If
End Sub
I also tried the Checked property.
This code is not working at all, if I put the whole If-End If section in the CheckedChanged event I get a StackOverflowException. What am I doing wrong?
The CheckBox is a custom control b.t.w.

If you'd like to prevent your Checkbox from automatically changing state and change the appearance with your own Click event, you can turn AutoCheck to false.
https://msdn.microsoft.com/en-us/library/system.windows.forms.checkbox.autocheck(v=vs.110).aspx
Information found thanks to this question: How to cancel RadioButton or CheckBox checked change
Public Class Form1
Private WithEvents btnApps As New clsChk
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
btnApps.AutoCheck = False
Me.Controls.Add(btnApps)
End Sub
Private Sub btnApps_Click(sender As Object, e As EventArgs) Handles btnApps.Click
Debug.WriteLine(btnApps.CheckState)
If btnApps.CheckState = CheckState.Checked Then
btnApps.CheckState = CheckState.Unchecked
Else
btnApps.CheckState = CheckState.Checked
End If
End Sub
End Class

Related

ContextMenuStrip Requires Two Right Clicks to Display

I like to create my contextmenu's programmatically. I generally do not add the items to the contextmenustrip until it is opening as the items that get displayed are dependent on other aspects of the design that are variable.
I have found that the contextmenustrips seem to require two right clicks to display. I've tried adding the menu items in different events (opening, opened, etc) and also manually setting the contextmenustrip's visibility to true to no avail.
I can't for the life of me figure out why two right clicks are necessary. If you create a blank winforms project and then replace all the code with this, it'll demonstrate the issue.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim currContextMenuStrip As New ContextMenuStrip
Me.ContextMenuStrip = currContextMenuStrip
AddHandler currContextMenuStrip.Opening, AddressOf ContextMenuStrip1_Opening
End Sub
Private Sub ContextMenuStrip1_Opening(sender As Object, e As CancelEventArgs)
Dim currContextMenuStrip As ContextMenuStrip = sender
Dim menuTxt As String = "&Find"
'only add the menu if it doesn't already exist
If (From f In currContextMenuStrip.Items Where f.text = menuTxt).Count = 0 Then
Dim newMenuItem As New ToolStripMenuItem
newMenuItem.Text = menuTxt
currContextMenuStrip.Items.Add(newMenuItem)
End If
End Sub
End Class
EDIT: Just figured out it seems to be connected to the fact that the contextmenustrip doesn't have any items on the first right click. If I add a dummy item, then hide it once other items are added, it works on the first right click. So confused!
This works:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim currContextMenuStrip As New ContextMenuStrip
Me.ContextMenuStrip = currContextMenuStrip
AddHandler currContextMenuStrip.Opening, AddressOf ContextMenuStrip1_Opening
'add a dummy item
Dim newMenuItem As New ToolStripMenuItem
newMenuItem.Text = "dummy"
currContextMenuStrip.Items.Add(newMenuItem)
End Sub
Private Sub ContextMenuStrip1_Opening(sender As Object, e As CancelEventArgs)
Dim currContextMenuStrip As ContextMenuStrip = sender
Dim menuTxt As String = "&Find"
'only add the menu if it doesn't already exist
If (From f In currContextMenuStrip.Items Where f.text = menuTxt).Count = 0 Then
Dim newMenuItem As New ToolStripMenuItem
newMenuItem.Text = menuTxt
currContextMenuStrip.Items.Add(newMenuItem)
End If
'hide the dummy item
Dim items As List(Of ToolStripMenuItem) = (From f As ToolStripMenuItem In currContextMenuStrip.Items Where f.Text = "dummy").ToList
items.First.visible = False
End Sub
End Class
If you really need to do things this way, one option is to create your own custom ContextMenuStrip that accounts for the behaviour when there are no items and the requirement for a dummy item. I used this code:
Imports System.ComponentModel
Public Class Form1
Private WithEvents menu As New ContextMenuStrip
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ContextMenuStrip = menu
End Sub
Private Sub menu_Opening(sender As Object, e As CancelEventArgs) Handles menu.Opening
If menu.Items.Count = 0 Then
menu.Items.AddRange({New ToolStripMenuItem("First"),
New ToolStripMenuItem("Second"),
New ToolStripMenuItem("Third")})
End If
End Sub
Private Sub menu_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles menu.ItemClicked
MessageBox.Show(e.ClickedItem.Text)
End Sub
End Class
and saw the same behaviour you describe. I then defined this class:
Public Class ContextMenuStripEx
Inherits ContextMenuStrip
Private dummyItem As ToolStripItem
Public ReadOnly Property IsInitialised As Boolean
Get
Return dummyItem Is Nothing
End Get
End Property
Public Sub New()
dummyItem = Items.Add(CStr(Nothing))
End Sub
''' <inheritdoc />
Protected Overrides Sub OnItemAdded(e As ToolStripItemEventArgs)
If Not IsInitialised Then
Items.Remove(dummyItem)
dummyItem = Nothing
End If
MyBase.OnItemAdded(e)
End Sub
End Class
and changed my form code to this:
Imports System.ComponentModel
Public Class Form1
Private WithEvents menu As New ContextMenuStripEx
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ContextMenuStrip = menu
End Sub
Private Sub menu_Opening(sender As Object, e As CancelEventArgs) Handles menu.Opening
If Not menu.IsInitialised Then
menu.Items.AddRange({New ToolStripMenuItem("First"),
New ToolStripMenuItem("Second"),
New ToolStripMenuItem("Third")})
End If
End Sub
Private Sub menu_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles menu.ItemClicked
MessageBox.Show(e.ClickedItem.Text)
End Sub
End Class
and it worked as desired. Note that the last code snippet uses the custom type and its custom property.
Thanks for all the help and suggestions! I ultimately decided to build the superset of menus in the Designer and then just show/hide at run time. That's probably faster on each right click then rebuilding the menu each time.
Microsoft has old style and new style context menus. The Popup event was used for the old style context menus and it received a plain EventArgs object. The new context menus use the Opening event which receives a CancelEventArgs object. If currContextMenuStrip.Items doesn't contain any items, e.Cancel will be set to True when the event handler is called (which caused the problem you encountered). The fix is to add the menu items and then set e.Cancel to False. It should display fine after that. To make sure items were actually added, the assignment of e.Cancel can be guarded with an if statement as follows:
If currContextMenuStrip.Items.Count <> 0 Then
e.Cancel = False
End If

Changing checkbox appearance to button

I am using a checkbox as a toggle switch (ON-OFF Button) by changing its appearance to Button using Checkbox.Appearance property.
When I run the VB.NET application, the Checkbox turns into a button only after the first click. Is it possible to change the appearance of the Checkbox to button as default? I also want the button to Popup when the user clicks "ON". I have tried changing the appearance using FlatStyle property, but it doesn't work.
I am using the following code:
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
CheckBox1.Appearance = System.Windows.Forms.Appearance.Button
If CheckBox1.Checked = True Then
CheckBox1.Text = "ON"
ElseIf CheckBox1.Checked = False Then
CheckBox1.Text = "OFF"
End If
End Sub
It is possible to select Appearance into the Load event of the form
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.CheckBox1.Appearance = Appearance.Button
End Sub

VB.net disable a TabPage of a TabControl

I currently have a form that uses TabControl which has 5 TabPages. I want to create a button that could disable a specific TabPage.
I have tried
TabPage1.Enabled = False
But it does not work. How do I do this?
you need to use the TabPages collection. Add a button to your form and try this
Private Sub Button1_Click( sender As Object, e As EventArgs) Handles Button1.Click
TabControl1.TabPages(0).Enabled =false
End Sub
It's a base zero array, so in your case it should be from 0-4.
Or you can access it from the text of the tab
Private Sub Button2_Click( sender As Object, e As EventArgs) Handles Button2.Click
Dim tabPage As TabPage
For Each tabPage In TabControl1.TabPages
If tabPage.Text ="TabPage2"
tabPage.Enabled =False
End If
Next
End Sub
Currently, the following two code blocks does the same thing: disables all the controls on that TabPage (Sets Control.Enabled = False). The tab itself is still visible and selectable from the TabControl, it is not hidden. The tab is selectable and all the elements appear disabled.
TabMyTab.Enabled = False
MyTabControl.TabPages(4).Enabled = False where the TabPages(4) is the 5th in the TabControl collection.
Your initial code should work if that is your intent.
If you want to disable the tab similar to i.e. button.Enabled = False which does not allow the control to be used, you will need to do something different as disabling a TabPage as in the code above disables all controls in that tab. If this is what you want, keep reading. A lot of programmers suggest using the TabControl to disallow the tab from being selected by selecting a different or the previously selected tab. This is the most effective way I know. I would implement this as follows:
Private PreviousTab As New TabPage
Private CurrentTab As New TabPage
Private Sub TabControlName_Deselected(ByVal sender As Object, ByVal e As System.Windows.Forms.TabControlEventArgs) Handles TabControlName.Deselected
PreviousTab = e.TabPage
End Sub
Private Sub TabControlName_Selected(ByVal sender As Object, ByVal e As System.Windows.Forms.TabControlEventArgs) Handles TabControlName.Selected
CurrentTab = e.TabPage
If (PreviousTab.Name <> CurrentTab.Name) And (CurrentTab.Name = UnselectableTab.Name) Then
MessageBox.Show("Tab disabled.", "Selection Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
TabControlName.SelectedTab = PreviousTab
End If
End Sub
Substitute your own values for "UnselectableTab" and "TabControlName" for your project.
You can combine the use of disabling the tab, that way the behavior is dynamic if you change which tabs are enabled or disabled in code.
Private Sub TabControl1_Deselected(sender As Object, e As TabControlEventArgs) Handles TabControl1.Deselected
PreviousTab = e.TabPage
End Sub
.
Private Sub TabControl1_Selected(sender As Object, e As TabControlEventArgs) Handles TabControl1.Selected
If Not e.TabPage.Enabled Then
TabControl1.SelectedTab = PreviousTab
End If
End Sub
You can disabled a tab by setting its Enabled property:
TabControl1.TabPages("tbPage1").Enabled = False

How to disable the accept button in code

In Microsoft Visual Basic 2010, a form has a property called AcceptButton. This can be set to the ok button of the form in the designer or by code, like this Me.AcceptButton = Me.OKbutton.
I would like to know how to disable this property in code, with something like Me.AcceptButton = Null, note this does not work. In the designer this property can be left set to (none).
The reason I would like to know how to achieve this is as follows. I have a textbox that the user enters data into; when they press enter an error check is done. This uses the following code
Private Sub textbox1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles textbox1.KeyDown
If e.KeyCode = Keys.Return Then
The problem I am having is that this code does not run if the AcceptButton property is enabled, due to the dual use of the return key. I would therefore like to temporarily disable then re-enable the AcceptButton property using code.
If I do not set the AcceptButton this code will run.
Don't tinker with the AcceptButton property, it gives important feedback to the user. Fix the real problem, set the TextBox' AcceptsReturn property to True.
If you still want to disable accept button use as Me.AcceptButton = Nothing
Leave the AcceptButton() property not set. Then, in your KeyDown() handler, if enter is pressed and everything passes your tests:
OKbutton.PerformClick()
Another approach is to disable your button and then only re-enable it when your conditions are met. Then you don't have to trap Enter in the TextBox handler. Here's a simply example:
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.AcceptButton = Me.OKbutton
Me.OKbutton.Enabled = False
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As System.EventArgs) Handles TextBox1.TextChanged
ValidateEntries()
End Sub
Private Sub ValidateEntries()
' ... put your logic in here to determine if all the fields in the form are in a valid state ...
' set the Enabled state of OKbutton accordingly:
Dim valid As Boolean = True ' assume valid until proven otherwise
' Made up validation code:
Dim value As Integer
If Integer.TryParse(TextBox1.Text, value) Then
If value < 60 Then
valid = False
End If
Else
valid = False
End If
Me.OKbutton.Enabled = valid
End Sub
Private Sub OKbutton_Click(sender As Object, e As System.EventArgs) Handles OKbutton.Click
MessageBox.Show("OK")
End Sub
End Class

Making combobox visible when it is disabled

I am disabling combobox in VB.net.
But in disable mode it not visible properly.
I tried changing both BackColor and ForeColor but it is not working.
Code :
cmbbox.BackColor = Color.FromName("Window")
or
cmbbox.ForeColor = Color.FromName("Window")
Please help
Dear Adam:
I am making my component enable false.But I want to make it viewable.You can reffer the link.This is what exacly I want but in VB.Net : A combobox that looks decent when it is disabled
To achieve disabling combobox without fading it, first change the dropdown style of the combobox to DropDownList, Then tweak with the events to achieve the goal.
Here is a piece of code by which you can achieve the same:
Public Class Form1
Dim selectindex As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ComboBox1.Items.Add("1")
ComboBox1.Items.Add("2")
ComboBox1.Items.Add("3")
ComboBox1.Items.Add("4")
selectindex = 3
ComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
ComboBox1.SelectedIndex = selectindex
End Sub
Private Sub ComboBox1_SelectionChangeCommitted(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectionChangeCommitted
ComboBox1.SelectedIndex = selectindex
End Sub
End Class
Create anew form Form1 and add a combobox to the form, then add the above code to get a readonly combobox.
Have a look at this thread which has a solution for a readonly combobox and the code is all VB.NET.
A version of their code is as follows. You'll need to but it inside a class of your own which inherits System.Windows.Forms.ComboBox
Private _ReadOnly As Boolean = False
Public Property [ReadOnly]() As Boolean
Get
Return _ReadOnly
End Get
Set(ByVal Value As Boolean)
_ReadOnly = Value
End Set
End Property
Public Overrides Function PreProcessMessage(ByRef msg As Message) As Boolean
'Prevent keyboard entry if control is ReadOnly
If _ReadOnly = True Then
'Check if its a keydown message
If msg.Msg = &H100 Then
'Get the key that was pressed
Dim key As Int32 = msg.WParam.ToInt32
'Ignore navigation keys
If key = Keys.Tab Or key = Keys.Left Or key = Keys.Right Then
'Do nothing
Else
Return True
End If
End If
End If
'Call base method so delegates receive event
Return MyBase.PreProcessMessage(msg)
End Function
Protected Overrides Sub WndProc(ByRef m As Message)
'Prevent list displaying if ReadOnly
If _ReadOnly = True Then
If m.Msg = &H201 OrElse m.Msg = &H203 Then
Return
End If
End If
'Call base method so delegates receive event
MyBase.WndProc(m)
End Sub
I've been looking for the same not long ago and ended up doing the following. You may not like it, but i'll share it in case. I am using TableLayoutPanel to arrange my controls on the form and then i am swapping the positions of the desired controls.
For example I've created the following Items:
Form1 Design
TableLayoutPanel1 (two columns, three rows)
TextBox1 Read-only = True, BackColor = White
ComboBox1 Visible = False, DropDownStyle = DropDownList, FlatStyle = Popup
Button1 (named it to Change)
Button2 (named it to Done) -> Visible = False
Runtime - Screenshots
Here is my code:
Public Class Form1
Private Sub SwapControls(tlp As TableLayoutPanel, ctr1 As Control, ctr2 As Control)
Dim ctl1pos As TableLayoutPanelCellPosition = tlp.GetPositionFromControl(ctr1)
ctr1.Visible = False
tlp.SetCellPosition(ctr1, tlp.GetPositionFromControl(ctr2))
ctr2.Visible = True
tlp.SetCellPosition(ctr2, ctl1pos)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SwapControls(TableLayoutPanel1, TextBox1, ComboBox1)
SwapControls(TableLayoutPanel1, Button1, Button2)
Label1.Select()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
SwapControls(TableLayoutPanel1, ComboBox1, TextBox1)
SwapControls(TableLayoutPanel1, Button2, Button1)
Label1.Select()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Select()
ComboBox1.SelectedIndex = 0
TextBox1.Text = ComboBox1.SelectedItem
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
TextBox1.Text = ComboBox1.SelectedItem
End Sub
End Class