DropDownCheckedListBox Issue - vb.net

Was looking at making a DropDownCheckedListBox for one of my forms. I found a complete source code that was on line.
Public Class DropDownCheckedListBox
Private Const T_DisplayListSize As Integer = 6
Private Const SelectNoneText As String = "(None Selected)"
Private Const SelectAllText As String = "(All Selected)"
Private Const SelectSomeText As String = "(Some Selected...)"
Private Frm As Form
Private Shadows LostFocus As Boolean
Private CodeValue As String
Private T_MustFill As Boolean
Private Shared m_ChkItemsString As String
Public Event DropDown()
Public Shadows Event TextChanged()
Public Sub New()
InitializeComponent()
InitializeNew()
End Sub
Private Sub InitializeNew()
Dim strTemp As String = Nothing
ListSize = T_DisplayListSize
T_DroppedDown = False
T_ListText = ""
T_MustFill = False
txt.Text = strTemp
Checklisbox.Hide()
Frm = New Form
With Frm
.ShowInTaskbar = False
.FormBorderStyle = FormBorderStyle.None
.ControlBox = False
.StartPosition = FormStartPosition.Manual
.TopMost = True
.Location = Checklisbox.Location
.Width = Checklisbox.Width
.Controls.Add(Checklisbox)
End With
SetSize()
End Sub
Private dataList() As String
Public Property Items() As String()
Get
Return dataList
End Get
Set(ByVal value As String())
dataList = value
End Set
End Property
Private ListSize As Integer
Public Property DisplayListSize() As Integer
Get
Return ListSize
End Get
Set(ByVal value As Integer)
ListSize = value
SetList()
End Set
End Property
Private T_DroppedDown As Boolean
Public ReadOnly Property DroppedDown() As Boolean
Get
Return T_DroppedDown
End Get
End Property
Private T_ListText As String
Public ReadOnly Property ListText() As String
Get
Return T_ListText
End Get
End Property
Private Sub ListButtonClick()
Dim strTemp As String
strTemp = T_ListText
If T_DroppedDown Then
T_DroppedDown = False
txt.Text = GetSelectedItems()
Checklisbox.Hide()
Frm.Hide()
txt.Focus()
If Not strTemp = T_ListText Then
RaiseEvent TextChanged()
End If
ElseIf Not LostFocus Then
T_DroppedDown = True
SetSize()
Frm.Show()
Checklisbox.Show()
Checklisbox.Focus()
RaiseEvent DropDown()
End If
LostFocus = False
End Sub
Private Function GetSelectedItems() As String
Dim strLst As String
Dim blnAllSelected As Boolean = False
strLst = ""
With Checklisbox
If .Items.Count > 0 Then
If .CheckedIndices.Count = 0 Then
strLst = SelectNoneText
Else
If .CheckedIndices.Count = .Items.Count Then
strLst = SelectAllText
Else
strLst = .CheckedIndices.Count & " selected" 'SelectSomeText
End If
End If
Else
strLst = SelectNoneText
End If
End With
Return strLst
End Function
'Removed code from this area that was just click, keystrokes events.
'Also Removed resize code.
Public Event SelectedIndexChanged(ByVal sender As DropDownCheckedListBox)
Public Shared Function GetItemsNameString(ByVal tempListBox As CheckedListBox) As String
m_ChkItemsString = ""
Try
If tempListBox.CheckedItems.Count > 0 Then
Dim tempItem As Object
For Each tempItem In tempListBox.CheckedItems
m_ChkItemsString = m_ChkItemsString & "," & tempItem.ToString()
Next
End If
m_ChkItemsString = m_ChkItemsString.Trim().Substring(1, m_ChkItemsString.Length - 1)
Catch ex As Exception
End Try
Return m_ChkItemsString
End Function
Public Sub setText(ByVal chklist As CheckedListBox)
If chklist.Items.Count > 0 Then
If chklist.CheckedIndices.Count = chklist.Items.Count Then
txt.Text = SelectAllText
Exit Sub
End If
If chklist.CheckedIndices.Count > 0 Then
txt.Text = chklist.CheckedIndices.Count & " selected"
ElseIf chklist.CheckedIndices.Count = 0 Then
txt.Text = SelectNoneText
End If
Else
txt.Text = SelectNoneText
End If
End Sub
Private Sub bChkLstBox_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
If Not dataList Is Nothing Then
If dataList.GetUpperBound(0) > 0 Then
For i As Integer = 0 To dataList.GetUpperBound(0)
If Not dataList(i) Is Nothing Then
Checklisbox.Items.Add(dataList(i))
End If
Next
End If
End If
End Sub
'Removed mouse events
End Class
This code works but I discovered a problem.
When I select items 1, 2, and 3 from the list and tell it to display the items in an list box I come up with the following: 1, 1, 2, 1, 2, 3.
I am still going over the code trying to figure it out but more experience individuals advice would be helpful.
Thanks in advance, and Apologies for the long code.
Edit:
Code to send items to Listbox
Dim Litems As New List(Of String)
ListBox1.Items.Clear()
Litems.Clear()
For Each I As String In DropDownCheckedListBox1.Checklisbox.CheckedItems
Litems.Add(I)
ListBox1.Items.AddRange(Litems.ToArray)
next

Move your AddRange line to outside the loop, otherwise, you keep re-adding the contents of your list to the ListBox:
Dim Litems As New List(Of String)
ListBox1.Items.Clear()
Litems.Clear()
For Each I As String In DropDownCheckedListBox1.Checklisbox.CheckedItems
Litems.Add(I)
next
ListBox1.Items.AddRange(Litems.ToArray)

Related

How can i detect my datagridview when keydown?

i have a codes for selecting right cell in datagridview when datagridview cell changed or press enter key
but codes running always when i press enter key
how can i do this only i'm in datagridview ?
Private KeyHandled As Boolean
Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
If FAT_TABLO.RowCount = 0 Then Exit Function
Dim icolumn As Integer = FAT_TABLO.CurrentCell.ColumnIndex
Dim irow As Integer = FAT_TABLO.CurrentCell.RowIndex
If keyData = Keys.Enter Then
If icolumn = FAT_TABLO.Columns.Count - 1 Then
FAT_TABLO.Rows.Add()
FAT_TABLO.CurrentCell = FAT_TABLO(0, irow + 1)
Else
FAT_TABLO.CurrentCell = FAT_TABLO(icolumn + 1, irow)
End If
Return True
Else
Return MyBase.ProcessCmdKey(msg, keyData)
End If
End Function
Try this
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'add new dgv
Dim Dgv1 As New DGV
With Dgv1
.AllowUserToAddRows = False
.Columns.Add("ColA", "A")
.Columns.Add("ColB", "B")
.Columns.Add("ColC", "C")
.Rows.Add(5)
.Dock = DockStyle.Top
End With
Me.Controls.Add(Dgv1)
End Sub
End Class
Class DGV
Inherits DataGridView
Protected Overrides Function ProcessDataGridViewKey(e As KeyEventArgs) As Boolean
If e.KeyData = Keys.Enter And Me.Rows.Count > 0 Then
With Me.CurrentCell
If .ColumnIndex < Me.Columns.Count - 1 Then
'Move to next cell
Me.CurrentCell = Me.Item(NextVisCol(.ColumnIndex + 1), .RowIndex)
Return True
ElseIf .ColumnIndex = Me.Columns.Count - 1 Then
If .RowIndex = Me.Rows.Count - 1 Then
'Add new row
Me.Rows.Add()
End If
'Move to first cell in next row
If Me.Rows(.RowIndex).IsNewRow = False Then Me.CurrentCell = Me.Item(NextVisCol(0), .RowIndex + 1)
Return True
End If
End With
End If
Return MyBase.ProcessDataGridViewKey(e)
End Function
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If keyData = Keys.Enter Then Return ProcessDataGridViewKey(New KeyEventArgs(Keys.Enter))
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
Private Function NextVisCol(Optional start As Integer = 0) As Integer
For i As Integer = start To Me.Columns.Count - 1
If Me.Columns(i).Visible Then Return i
Next
For i As Integer = 0 To Me.Columns.Count - 1
If Me.Columns(i).Visible Then Return i
Next
Throw New Exception("All columns are not visible")
End Function
End Class

Error adding control from toolbox to windows form

i have class inherited from textbox , and when i try to add the control from the toolbox i have this error in the picture.
this is class inherited from textbox control ,using listbox control to choose from auto complete list
Public Structure Account
Dim Name As String
Dim Number As String
Public Sub New(Namee As String, Num As String)
Name = Namee
Number = Num
End Sub
Public Overrides Function ToString() As String
Return Name
End Function
End Structure
Public Class AutoCompleteTextBox
Inherits TextBox
Private ACL As List(Of Account), CACL As List(Of Account)
Private CaseSensitive As Boolean
Private MinChar As Integer
Private LS As ListBox
Private OLDText As String
Private PN As Panel
Public Sub New()
MyBase.New
MinTypedCharacters = 2
CaseSesitivity = False
ACL = New List(Of Account)
LS = New ListBox
LS.Name = "SeggestionListBox"
LS.Font = Font
LS.Visible = True
PN = New Panel
PN.Visible = False
PN.Font = Font
PN.AutoSizeMode = AutoSizeMode.GrowAndShrink
PN.ClientSize = New Size(1, 1)
PN.Name = "SeggestionPanel"
PN.Padding = New Padding(0, 0, 0, 0)
PN.Margin = New Padding(0, 0, 0, 0)
PN.BackColor = Color.Transparent
PN.ForeColor = Color.Transparent
PN.PerformLayout()
If Not PN.Controls.Contains(LS) Then
PN.Controls.Add(LS)
End If
LS.Dock = DockStyle.Fill
LS.SelectionMode = SelectionMode.One
AddHandler LS.KeyDown, AddressOf LS_KeyDown
AddHandler LS.MouseClick, AddressOf LS_MouseClick
AddHandler LS.MouseDoubleClick, AddressOf LS_MouseDoubleClick
CACL = New List(Of Account)
LS.DataSource = CACL
OLDText = Text
End Sub
#Region "Properties"
Public Property AutoCompleteList As List(Of Account)
Get
Return ACL
End Get
Set(value As List(Of Account))
ACL.Clear()
ACL = value
End Set
End Property
Public Property CaseSesitivity As Boolean
Get
Return CaseSensitive
End Get
Set(value As Boolean)
CaseSensitive = value
End Set
End Property
Public Property MinTypedCharacters As Integer
Get
Return MinChar
End Get
Set(value As Integer)
MinChar = value
End Set
End Property
Public Property SelectedIndex As Integer
Get
Return LS.SelectedIndex
End Get
Set(value As Integer)
If LS.Items.Count <> 0 Then
LS.SelectedIndex = value
End If
End Set
End Property
Private ReadOnly Property ParentForm As Form
Get
Return Me.Parent.FindForm
End Get
End Property
#End Region
Public Sub HideSuggestionListBox()
If Not ParentForm Is Nothing Then
PN.Hide()
If ParentForm.Controls.Contains(PN) Then
ParentForm.Controls.Remove(PN)
End If
End If
End Sub
Private Function SelectItem() As Boolean
If LS.Items.Count > 0 AndAlso LS.SelectedIndex > -1 Then
Text = LS.SelectedItem.ToString
HideSuggestionListBox()
End If
Return True
End Function
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
If e.KeyCode = Keys.Up Then
MoveSelection(SelectedIndex - 1)
e.Handled = True
ElseIf e.KeyCode = Keys.Down Then
MoveSelection(SelectedIndex + 1)
e.Handled = True
ElseIf e.KeyCode = Keys.PageUp Then
MoveSelection(SelectedIndex - 10)
e.Handled = True
ElseIf e.KeyCode = Keys.PageDown Then
MoveSelection(SelectedIndex + 10)
e.Handled = True
ElseIf e.KeyCode = Keys.Enter Then
SelectItem()
e.Handled = True
Else
MyBase.OnKeyDown(e)
End If
End Sub
Protected Overrides Sub OnLostFocus(e As EventArgs)
If Not PN.ContainsFocus Then
MyBase.OnLostFocus(e)
If Not CheckItem(Text) Then
Text = ""
End If
HideSuggestionListBox()
End If
End Sub
Protected Overrides Sub OnTextChanged(e As EventArgs)
If Not DesignMode Then
ShowSuggests()
End If
MyBase.OnTextChanged(e)
OLDText = Text
End Sub
Private Sub LS_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
If (e.KeyCode = Keys.Enter) Then
Me.SelectItem()
e.Handled = True
End If
End Sub
Private Sub LS_MouseClick(ByVal sender As Object, ByVal e As MouseEventArgs)
' select the current item
Me.SelectItem()
MsgBox(LS.SelectedItem.number)
End Sub
Private Sub LS_MouseDoubleClick(ByVal sender As Object, ByVal e As MouseEventArgs)
Me.SelectItem()
End Sub
Private Function CheckItem(ItemSTR As String) As Boolean
For Each STR As Account In ACL
If ItemSTR.ToLower = STR.ToString.ToLower Then
Return True
Exit Function
End If
Next
Return False
End Function
Private Sub MoveSelection(Index As Integer)
If Index <= -1 Then
SelectedIndex = 0
ElseIf Index > (LS.Items.Count - 1) Then
SelectedIndex = LS.Items.Count - 1
Else
SelectedIndex = Index
End If
End Sub
Private Sub ShowSuggests()
If Text.Length >= MinTypedCharacters Then
PN.SuspendLayout()
If Text.Length > 0 AndAlso OLDText = Text.Substring(0, Text.Length - 1) Then
UpdateCurrentAutoCompleteList()
ElseIf OLDText.Length > 0 AndAlso Text = OLDText.Substring(0, OLDText.Length - 1) Then
UpdateCurrentAutoCompleteList()
Else
UpdateCurrentAutoCompleteList()
End If
If Not CACL Is Nothing AndAlso CACL.Count > 0 Then
PN.Show()
PN.BringToFront()
Focus()
Else
HideSuggestionListBox()
End If
PN.ResumeLayout()
Else
HideSuggestionListBox()
End If
End Sub
Private Sub UpdateCurrentAutoCompleteList()
CACL.Clear()
For Each STR As Account In ACL
If CaseSesitivity = True Then
If STR.ToString.IndexOf(Text) > -1 Then
CACL.Add(STR)
End If
Else
If STR.ToString.ToLower.IndexOf(Text.ToLower) > -1 Then
CACL.Add(STR)
End If
End If
Next
If CACL.Count > 0 Then
UpdateListBoxItems()
Else
HideSuggestionListBox()
End If
End Sub
Private Sub UpdateListBoxItems()
If Not ParentForm Is Nothing Then
PN.Width = Width
'PN.Height = ParentForm.ClientSize.Height - Height - Location.Y
Dim F As Integer = ParentForm.ClientSize.Height - Height - Location.Y
Dim Ten As Integer = Font.Height * 10
Dim CUr As Integer = Font.Height * (CACL.Count + 1)
If F < CUr Then
PN.Height = F
ElseIf CUr < Ten Then
PN.Height = CUr
ElseIf Ten < F Then
PN.Height = Ten
Else
PN.Height = F
End If
'PN.Height = Font.Height * 10
PN.Location = Location + New Size(0, Height)
If Not ParentForm.Controls.Contains(PN) Then
ParentForm.Controls.Add(PN)
End If
CType(LS.BindingContext(CACL), CurrencyManager).Refresh()
End If
End Sub
End Class
firstly i used list(of string) before using the structure account .
the problem appears after using the structure
Any Idea about this error ?
**** additional picture show another problem after substitutes the structure with class and adds attribute.
***** changed the Structure to class
<Serializable> Public Class Account
Private Nam As String
Private Numbe As String
Public Sub New(Namee As String, Num As String)
Name = Namee
Number = Num
End Sub
Public Property Name As String
Get
Return Nam
End Get
Set(value As String)
Nam = value
End Set
End Property
Public Property Number As String
Get
Return Numbe
End Get
Set(value As String)
Numbe = value
End Set
End Property
Public Overrides Function ToString() As String
Return Name
End Function
End Class
Problem Resolved*
i will share the solve with you.
all the problem is coming from the line
ACL = New List(Of Account)
and the line
CACL = New List(Of Account)
because it declare new list(of account) in design time.
i solved the problem by deleting the both of line and modified the property (AutoCompleteList) to be like that.
Public WriteOnly Property AutoCompleteList As List(Of Account)
Set(value As List(Of Account))
ACL = value
CACL = New List(Of Account)
End Set
End Property
and the final code will be like that:-
the structure:
Public Structure Account
Public Name As String
Public Number As String
Public Sub New(Namee As String, Num As String)
Name = Namee
Number = Num
End Sub
Public Overrides Function ToString() As String
Return Name
End Function
End Structure
the class:
Public Class AutoCompleteTextBox
Inherits TextBox
Private ACL As List(Of Account), CACL As List(Of Account)
Private CaseSensitive As Boolean
Private MinChar As Integer
Private LS As ListBox
Private OLDText As String
Private PN As Panel
Public Sub New()
MyBase.New
MinTypedCharacters = 2
CaseSesitivity = False
LS = New ListBox
LS.Name = "SeggestionListBox"
LS.Font = Font
LS.Visible = True
PN = New Panel
PN.Visible = False
PN.Font = Font
PN.AutoSizeMode = AutoSizeMode.GrowAndShrink
PN.ClientSize = New Size(1, 1)
PN.Name = "SeggestionPanel"
PN.Padding = New Padding(0, 0, 0, 0)
PN.Margin = New Padding(0, 0, 0, 0)
PN.BackColor = Color.Transparent
PN.ForeColor = Color.Transparent
PN.PerformLayout()
If Not PN.Controls.Contains(LS) Then
PN.Controls.Add(LS)
End If
LS.Dock = DockStyle.Fill
LS.SelectionMode = SelectionMode.One
AddHandler LS.KeyDown, AddressOf LS_KeyDown
AddHandler LS.MouseClick, AddressOf LS_MouseClick
AddHandler LS.MouseDoubleClick, AddressOf LS_MouseDoubleClick
LS.DataSource = CACL
OLDText = Text
End Sub
Public WriteOnly Property AutoCompleteList As List(Of Account)
Set(value As List(Of Account))
'ACL.Clear()
ACL = value
CACL = New List(Of Account)
End Set
End Property
Public Property CaseSesitivity As Boolean
Get
Return CaseSensitive
End Get
Set(value As Boolean)
CaseSensitive = value
End Set
End Property
Public Property MinTypedCharacters As Integer
Get
Return MinChar
End Get
Set(value As Integer)
MinChar = value
End Set
End Property
Public Property SelectedIndex As Integer
Get
Return LS.SelectedIndex
End Get
Set(value As Integer)
If LS.Items.Count <> 0 Then
LS.SelectedIndex = value
End If
End Set
End Property
Private ReadOnly Property ParentForm As Form
Get
Return Me.Parent.FindForm
End Get
End Property
Public Sub HideSuggestionListBox()
If Not ParentForm Is Nothing Then
PN.Hide()
If ParentForm.Controls.Contains(PN) Then
ParentForm.Controls.Remove(PN)
End If
End If
End Sub
Private Function SelectItem() As Boolean
If LS.Items.Count > 0 AndAlso LS.SelectedIndex > -1 Then
Text = LS.SelectedItem.ToString
MsgBox(LS.SelectedItem.number)
HideSuggestionListBox()
End If
Return True
End Function
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
If e.KeyCode = Keys.Up Then
MoveSelection(SelectedIndex - 1)
e.Handled = True
ElseIf e.KeyCode = Keys.Down Then
MoveSelection(SelectedIndex + 1)
e.Handled = True
ElseIf e.KeyCode = Keys.PageUp Then
MoveSelection(SelectedIndex - 10)
e.Handled = True
ElseIf e.KeyCode = Keys.PageDown Then
MoveSelection(SelectedIndex + 10)
e.Handled = True
ElseIf e.KeyCode = Keys.Enter Then
SelectItem()
e.Handled = True
Else
MyBase.OnKeyDown(e)
End If
End Sub
Protected Overrides Sub OnLostFocus(e As EventArgs)
If Not PN.ContainsFocus Then
MyBase.OnLostFocus(e)
If Not CheckItem(Text) Then
Text = ""
End If
HideSuggestionListBox()
End If
End Sub
Protected Overrides Sub OnTextChanged(e As EventArgs)
If Not DesignMode Then
ShowSuggests()
End If
MyBase.OnTextChanged(e)
OLDText = Text
End Sub
Private Sub LS_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
If (e.KeyCode = Keys.Enter) Then
Me.SelectItem()
e.Handled = True
End If
End Sub
Private Sub LS_MouseClick(ByVal sender As Object, ByVal e As MouseEventArgs)
' select the current item
Me.SelectItem()
MsgBox(LS.SelectedItem.number)
End Sub
Private Sub LS_MouseDoubleClick(ByVal sender As Object, ByVal e As MouseEventArgs)
Me.SelectItem()
End Sub
Private Function CheckItem(ItemSTR As String) As Boolean
For Each STR As Account In ACL
If ItemSTR.ToLower = STR.ToString.ToLower Then
Return True
Exit Function
End If
Next
Return False
End Function
Private Sub MoveSelection(Index As Integer)
If Index <= -1 Then
SelectedIndex = 0
ElseIf Index > (LS.Items.Count - 1) Then
SelectedIndex = LS.Items.Count - 1
Else
SelectedIndex = Index
End If
End Sub
Private Sub ShowSuggests()
If Text.Length >= MinTypedCharacters Then
PN.SuspendLayout()
If Text.Length > 0 AndAlso OLDText = Text.Substring(0, Text.Length - 1) Then
UpdateCurrentAutoCompleteList()
ElseIf OLDText.Length > 0 AndAlso Text = OLDText.Substring(0, OLDText.Length - 1) Then
UpdateCurrentAutoCompleteList()
Else
UpdateCurrentAutoCompleteList()
End If
If Not CACL Is Nothing AndAlso CACL.Count > 0 Then
PN.Show()
PN.BringToFront()
Focus()
Else
HideSuggestionListBox()
End If
PN.ResumeLayout()
Else
HideSuggestionListBox()
End If
End Sub
Private Sub UpdateCurrentAutoCompleteList()
CACL.Clear()
For Each STR As Account In ACL
If CaseSesitivity = True Then
If STR.ToString.IndexOf(Text) > -1 Then
CACL.Add(STR)
End If
Else
If STR.ToString.ToLower.IndexOf(Text.ToLower) > -1 Then
CACL.Add(STR)
End If
End If
Next
If CACL.Count > 0 Then
UpdateListBoxItems()
Else
HideSuggestionListBox()
End If
End Sub
Sub Fill()
For Each A As Account In CACL
LS.Items.Add(A)
Next
End Sub
Private Sub UpdateListBoxItems()
If Not ParentForm Is Nothing Then
PN.Width = Width
'PN.Height = ParentForm.ClientSize.Height - Height - Location.Y
Dim F As Integer = ParentForm.ClientSize.Height - Height - Location.Y
Dim Ten As Integer = Font.Height * 10
Dim CUr As Integer = Font.Height * (CACL.Count + 1)
If F < CUr Then
PN.Height = F
ElseIf CUr < Ten Then
PN.Height = CUr
ElseIf Ten < F Then
PN.Height = Ten
Else
PN.Height = F
End If
'PN.Height = Font.Height * 10
PN.Location = Location + New Size(0, Height)
If Not ParentForm.Controls.Contains(PN) Then
ParentForm.Controls.Add(PN)
End If
Fill()
End If
End Sub
End Class
thank you all.

BackgroundWorker and shared class

I have a NumericUpDown control in the main thread.
I create an instance of a public class_A that stores the NumericUpDown value.
I create a BackgroundWorker that runs a separate thread.
In the BackgroundWorker thread I create an instance of a class_B that recalls the argument from the instance of class_A.
I don't understand why the instance of the class_A just created before, its result as Nothing.
Here is the code:
Imports System.ComponentModel
Public Class Form1
Dim WithEvents bgw As New BackgroundWorker
Dim WithEvents bgw2 As New BackgroundWorker
Dim lSide As Label
Public nudSide As NumericUpDown
Dim bCalculate As Button
Dim bCalculate2 As Button
Dim tbLog As TextBox
Dim calc As calc
Public calc2 As calc2
Public Delegate Function d_getSide() As Double
Public getSide As New d_getSide(AddressOf rungetSide)
Public Side As c_Side
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Size = New Size(400, 160)
bgw.WorkerSupportsCancellation = True
bgw2.WorkerSupportsCancellation = True
lSide = New Label
With lSide
.Text = "Side"
.Size = New Size(40, 20)
.Location = New Point(10, 10)
End With
Me.Controls.Add(lSide)
nudSide = New NumericUpDown
With nudSide
.Size = New Size(40, 20)
.Location = New Point(lSide.Location.X + lSide.Size.Width, lSide.Location.Y)
.DecimalPlaces = 0
.Minimum = 1
.Maximum = 100
.Increment = 1
.Value = 1
End With
Me.Controls.Add(nudSide)
bCalculate = New Button
With bCalculate
.Text = "Calculate"
.Size = New Size(60, 20)
.Location = New Point(nudSide.Location.X + nudSide.Size.Width + 40, nudSide.Location.Y)
AddHandler .Click, AddressOf bCalculate_Click
End With
Me.Controls.Add(bCalculate)
bCalculate2 = New Button
With bCalculate2
.Text = "Calculate 2"
.Size = New Size(60, 20)
.Location = New Point(bCalculate.Location.X + bCalculate.Size.Width + 10, bCalculate.Location.Y)
AddHandler .Click, AddressOf bCalculate2_Click
End With
Me.Controls.Add(bCalculate2)
tbLog = New TextBox
With tbLog
.Size = New Size(250, 60)
.Location = New Point(lSide.Location.X, lSide.Location.Y + 40)
.Multiline = True
.ScrollBars = ScrollBars.Vertical
End With
Me.Controls.Add(tbLog)
End Sub
Private Sub bCalculate_Click()
bgw.RunWorkerAsync(nudSide.Value)
End Sub
Private Sub bgw_Dowork(sender As Object, e As DoWorkEventArgs) Handles bgw.DoWork
'example 1)
'passing argument throught backGroundWorker
calc = New calc(e.Argument)
End Sub
Private Sub bgw_Runworkercompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
getResult()
End Sub
Private Sub bCalculate2_Click()
'here i create an instance of the Side class (expose the side property)
Side = New c_Side
bgw2.RunWorkerAsync()
End Sub
Private Sub bgw2_Dowork(sender As Object, e As DoWorkEventArgs) Handles bgw2.DoWork
'example 2)
' in the backgroundworker thread i create an instance of the class calc2
calc2 = New calc2()
End Sub
Private Sub bgw2_Runworkercompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgw2.RunWorkerCompleted
getResult2()
End Sub
Private Sub write(ByVal message As String)
With tbLog
.SelectionStart = .Text.Length
.SelectedText = vbCrLf & message
End With
End Sub
Private Sub getResult()
tbLog.Clear()
write("area = " & calc.area & " cm^2")
write("volume = " & calc.volume & " cm^3")
End Sub
Private Sub getResult2()
tbLog.Clear()
write("area = " & calc2.area & " cm^2")
write("volume = " & calc2.volume & " cm^3")
End Sub
Public Function rungetSide() As Double
If Me.InvokeRequired Then
Me.Invoke(getSide)
Else
Return Side.Side
End If
Return Side.Side
End Function
End Class
Class calc
Sub New(ByVal Side As Double)
_area = Side ^ 2
_volume = Side ^ 3
End Sub
Private _area As Double
Public Property area As Double
Get
Return Math.Round(_area, 2)
End Get
Set(value As Double)
_area = Math.Round(value, 2)
End Set
End Property
Private _volume As Double
Public Property volume As Double
Get
Return Math.Round(_volume, 2)
End Get
Set(value As Double)
_volume = Math.Round(value, 2)
End Set
End Property
End Class
Public Class calc2
Sub New()
'the constructor, recall the value from the instance (public) of the class 'Side' just built in the main thread
'but i don't understand why the instance it's nothing
_area = Form1.Side.Side ^ 2
_volume = Form1.Side.Side ^ 3
End Sub
Private _area As Double
Public Property area As Double
Get
Return Math.Round(_area, 2)
End Get
Set(value As Double)
_area = Math.Round(value, 2)
End Set
End Property
Private _volume As Double
Public Property volume As Double
Get
Return Math.Round(_volume, 2)
End Get
Set(value As Double)
_volume = Math.Round(value, 2)
End Set
End Property
End Class
Public Class c_Side
Sub New()
_Side = Form1.nudSide.Value
'_Side = Form1.rungetSide
End Sub
Private _Side As Double
Public Property Side As Double
Get
Return Math.Round(_Side, 2)
End Get
Set(value As Double)
_Side = Math.Round(value, 2)
End Set
End Property
End Class
What I'm looking for is to create an instance of class_A in the main thread and store the NumericUpDown value, and in a separate thread (BackgroundWorker) create an instance of class_B and obtain the value of the NumericUpDown control, just before stored in the instance of class_A.
I've found the solution.
Just declare the variable as Public Shared
Public Shared Side As c_Side
So it's visible from all the application, and so, from all the threads.
So when i start the thread (or when i want or when i need), i backup all the values of the UI controls in a Public Shared instance of a Public Class, that can be 'read' from the backGroundWorker thread.

sending sms to multiple recipients using gsm in vb.net

Imports System
Imports System.Threading
Imports System.ComponentModel
Imports System.IO.Ports
Public Class SMSCOMMS
Private WithEvents SMSPort As SerialPort
Private SMSThread As Thread
Private ReadThread As Thread
Shared _Continue As Boolean = False
Shared _ContSMS As Boolean = False
Private _Wait As Boolean = False
Shared _ReadPort As Boolean = False
Public Event Sending(ByVal Done As Boolean)
Public Event DataReceived(ByVal Message As String)
Public Sub New(ByRef COMMPORT As String)
SMSPort = New SerialPort
With SMSPort
.PortName = COMMPORT
.BaudRate = 115200
.Parity = Parity.None
.DataBits = 8
.StopBits = StopBits.One
.Handshake = Handshake.RequestToSend
.DtrEnable = True
.RtsEnable = True
.NewLine = vbCrLf
End With
'ReadThread = New Thread(AddressOf ReadPort)
End Sub
Public Sub SendSMS(ByVal CellNumber As String, ByVal SMSMessage As String)
Dim MyMessage As String = Nothing
If SMSMessage.Length <= 160 Then
MyMessage = SMSMessage
Else
MyMessage = Mid(SMSMessage, 1, 160)
End If
If IsOpen = True Then
SMSPort.WriteLine("AT+CMGS=" & CellNumber & vbCr)
_ContSMS = False
Thread.SpinWait(200)
SMSPort.WriteLine(MyMessage & vbCrLf & Chr(26))
_Continue = False
Thread.SpinWait(200)
RaiseEvent Sending(False)
End If
End Sub
Private Sub ReadPort()
Dim SerialIn As String = Nothing
Dim RXBuffer(SMSPort.ReadBufferSize) As Byte
Dim SMSMessage As String = Nothing
Dim Strpos As Integer = 0
Dim TmpStr As String = Nothing
While SMSPort.IsOpen = True
If (SMSPort.BytesToRead <> 0) And (
SMSPort.IsOpen = True) Then
While SMSPort.BytesToRead <> 0
SMSPort.Read(RXBuffer, 0, SMSPort.ReadBufferSize)
SerialIn =
SerialIn & System.Text.Encoding.ASCII.GetString(
RXBuffer)
If SerialIn.Contains(">") = True Then
_ContSMS = True
End If
If SerialIn.Contains("+CMGS:") = True Then
_Continue = True
RaiseEvent Sending(True)
_Wait = False
SerialIn = String.Empty
ReDim RXBuffer(SMSPort.ReadBufferSize)
End If
End While
RaiseEvent DataReceived(SerialIn)
SerialIn = String.Empty
ReDim RXBuffer(SMSPort.ReadBufferSize)
End If
End While
End Sub
Public ReadOnly Property IsOpen() As Boolean
Get
If SMSPort.IsOpen = True Then
IsOpen = True
Else
IsOpen = False
End If
End Get
End Property
Public Sub Open()
If IsOpen = False Then
SMSPort.Open()
'ReadThread.Start()
End If
End Sub
Public Sub Close()
If IsOpen = True Then
SMSPort.Close()
End If
End Sub
End Class
i tried sending sms using gsm modem in vb.net using this code. This is working fine but when i tried sending sms to multiple recipient the first recipient only receives the sms while the others no reponse.
This is the code for the sending sms:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim sms As SMSCOMMS
sms = New SMSCOMMS("COM25")
sms.Open()
sms.SendSMS("+63*******", "123")
Threading.Thread.SpinWait(200)
sms.SendSMS("+63*******", "456")
sms.Close()
End Sub

vb.net: How to prevent the dropdown of a checked combobox from closing after checking or unchecking an item

I would like to prevent the dropdown list from closing when the user checks or unchecks a checkbox in a checked combobox.
I have copied some Microsoft code to created a checked combobox. As it didn't work out-of-the-box, I did some customizing.
Here's my code:
Imports System.ComponentModel
Imports System.Collections.ObjectModel
Public Class CheckedCombobox
Inherits ComboBox
Public Event ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs)
<Browsable(False)> _
Public Overloads ReadOnly Property Items() As ComboBox.ObjectCollection
Get
Return MyBase.Items
End Get
End Property
Private WithEvents _ItemCollection As New ObservableCollection(Of String)
Public Property ItemCollection As ObservableCollection(Of String)
Get
Return _ItemCollection
End Get
Set(value As ObservableCollection(Of String))
_ItemCollection = value
End Set
End Property
Private _ItemDictionary As New Dictionary(Of String, Boolean)
Public ReadOnly Property ItemDictionary As Dictionary(Of String, Boolean)
Get
Return _ItemDictionary
End Get
End Property
Public ReadOnly Property CheckedItemCollection As List(Of String)
Get
Return New List(Of String)(From item In ItemDictionary Where item.Value = True Select item.Key)
End Get
End Property
Public ReadOnly Property UnCheckedItemCollection As List(Of String)
Get
Return New List(Of String)(From item In ItemDictionary Where item.Value = False Select item.Key)
End Get
End Property
Public Sub setCheckState(ByVal key As String, ByVal checkstate As Boolean)
_ItemDictionary(key) = checkstate
End Sub
Public Function getCheckState(ByVal key As String)
Return (_ItemDictionary(key))
End Function
Public Sub New()
Me.DrawMode = Windows.Forms.DrawMode.OwnerDrawVariable
End Sub
Protected Overrides Sub OnCreateControl()
MyBase.OnCreateControl()
For Each item In ItemCollection
_ItemDictionary.Add(item, False)
Next
End Sub
Private Sub ItemsChanged(ByVal sender As Object, ByVal e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) Handles _ItemCollection.CollectionChanged
Select Case e.Action
Case Specialized.NotifyCollectionChangedAction.Add
If e.NewStartingIndex = ItemDictionary.Count Then
_ItemDictionary.Add(e.NewItems(0), False)
MyBase.Items.Add(e.NewItems(0))
End If
Case Specialized.NotifyCollectionChangedAction.Remove
_ItemDictionary.Remove(MyBase.Items(e.OldStartingIndex))
MyBase.Items.RemoveAt(e.OldStartingIndex)
Case Specialized.NotifyCollectionChangedAction.Move
Dim _item As Object = MyBase.Items(e.OldStartingIndex)
MyBase.Items.RemoveAt(e.OldStartingIndex)
MyBase.Items.Insert(e.NewStartingIndex, _item)
Case Specialized.NotifyCollectionChangedAction.Replace
Throw New Exception("Not implemented yet!")
Case Specialized.NotifyCollectionChangedAction.Reset
Dim _checkeditems As New List(Of String)(CheckedItemCollection)
MyBase.Items.Clear()
MyBase.Items.AddRange(_ItemCollection.ToArray)
_ItemDictionary.Clear()
For Each item In _ItemCollection
_ItemDictionary.Add(item, _checkeditems.Contains(item))
Next
End Select
Me.Invalidate()
End Sub
Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
e.DrawBackground()
Dim p As Point = e.Bounds.Location
If e.Index >= 0 Then
p.Offset(1, 1)
If getCheckState(MyBase.Items(e.Index)) Then
CheckBoxRenderer.DrawCheckBox(e.Graphics, p, VisualStyles.CheckBoxState.CheckedNormal)
Else
CheckBoxRenderer.DrawCheckBox(e.Graphics, p, VisualStyles.CheckBoxState.UncheckedNormal)
End If
p.Offset(12, 0)
e.Graphics.DrawString(MyBase.GetItemText(Me.Items(e.Index)), e.Font, New SolidBrush(e.ForeColor), p.X, p.Y)
End If
If e.State = DrawItemState.Selected Then
e.DrawFocusRectangle()
End If
MyBase.OnDrawItem(e)
End Sub
Private Sub checkedChanged(ByVal index As Integer)
Dim checked As Boolean = _ItemDictionary(MyBase.Items.Item(index))
If checked Then
_ItemDictionary(MyBase.Items.Item(index)) = False
RaiseEvent ItemCheck(Me, New ItemCheckEventArgs(index, CheckState.Unchecked, CheckState.Checked))
Else
_ItemDictionary(MyBase.Items.Item(index)) = True
RaiseEvent ItemCheck(Me, New ItemCheckEventArgs(index, CheckState.Checked, CheckState.Unchecked))
End If
Me.Invalidate()
End Sub
Private n As nWindow = Nothing
Private Const WM_CTLCOLORLISTBOX As Integer = &H134
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
If m.Msg = WM_CTLCOLORLISTBOX Then
If n Is Nothing Then
n = New nWindow(Me)
n.AssignHandle(m.LParam)
AddHandler n.checkedChanged, AddressOf checkedChanged
End If
End If
End Sub
Private Sub CheckedCombobox_Click(sender As Object, e As System.EventArgs) Handles Me.SelectedIndexChanged
Debugger.Break()
End Sub
End Class
Public Class nWindow
Inherits NativeWindow
Private Const WM_LBUTTONDOWN As Integer = &H201
Private _combobox As CheckedCombobox
Public Event checkedChanged(ByVal index As Integer)
Public Sub New(ByVal cb As CheckedCombobox)
_combobox = cb
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_LBUTTONDOWN Then
Dim itemHeight As Integer = _combobox.ItemHeight
If New Point(m.LParam.ToInt32).Y \ itemHeight <= _combobox.Items.Count - 1 And New Point(m.LParam.ToInt32).Y \ itemHeight >= 0 Then
If New Point(m.LParam.ToInt32).X >= 1 And New Point(m.LParam.ToInt32).X <= 11 Then
RaiseEvent checkedChanged(_combobox.SelectedIndex)
End If
End If
End If
MyBase.WndProc(m)
End Sub
End Class
The code below seems to work correctly. It does what I set out to do.
(Note: I have only shown the changed routines)
Private Sub checkedChanged(ByVal index As Integer)
Dim checked As Boolean = _ItemDictionary(MyBase.Items.Item(index))
If checked Then
_ItemDictionary(MyBase.Items.Item(index)) = False
RaiseEvent ItemCheck(Me, New ItemCheckEventArgs(index, CheckState.Unchecked, CheckState.Checked))
Else
_ItemDictionary(MyBase.Items.Item(index)) = True
RaiseEvent ItemCheck(Me, New ItemCheckEventArgs(index, CheckState.Checked, CheckState.Unchecked))
End If
Me.SelectedIndex = -1
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_LBUTTONDOWN Then
Dim itemHeight As Integer = _combobox.ItemHeight
If New Point(m.LParam.ToInt32).Y \ itemHeight <= _combobox.Items.Count - 1 And New Point(m.LParam.ToInt32).Y \ itemHeight >= 0 Then
If New Point(m.LParam.ToInt32).X >= 1 And New Point(m.LParam.ToInt32).X <= 11 Then
RaiseEvent checkedChanged(_combobox.SelectedIndex)
Return
End If
End If
End If
MyBase.WndProc(m)
End Sub
I am not hundred percent sure about not calling MyBase.WndProc(), but I did not notice any side-effects yet.