VB.net basic error with String <-> Char Conversion - vb.net

I was programming a little game to pratice myself and i went on an error I weren't able to fix :S. This is the start of an hanging game. (Dont know if its the correct name in english :) ) I need to take a word from a file, 1 per line, and let the player guess the word with a limited numbers of try.
I think my error is related to string/char comparaison and manipulation or, what i write in the text label. I tryed to find some tutorial or problem already solved on internet but nothing was really the same as this ... :(
I change the type of variable many time, read the debugger line per line but I never finded what was wrong .. :S If you are good with VB, plz help me fix that :O (you can also give your comment/improve)
Thx, TheFlame
Code:
Imports System.IO
Public Class Pendu
Public Structure StructMot
Public MotSecret() As Char
Public LettreDecouverte() As Char
End Structure
Dim Mot As StructMot
Dim i As Integer = 0
Private Sub ButtonA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonA.Click, ButtonB.Click,
ButtonC.Click, ButtonD.Click, ButtonE.Click, ButtonF.Click, ButtonG.Click, ButtonH.Click, ButtonI.Click, ButtonJ.Click,
ButtonK.Click, ButtonL.Click, ButtonM.Click, ButtonN.Click, ButtonO.Click, ButtonP.Click, ButtonQ.Click, ButtonR.Click,
ButtonS.Click, ButtonT.Click, ButtonU.Click, ButtonV.Click, ButtonW.Click, ButtonX.Click, ButtonY.Click, ButtonZ.Click
i = i + 1
ActiveControl.Visible = False
PictureBox1.Image = ImageList1.Images(i - 1)
Dim j As Integer = 0
For j = 0 To Mot.MotSecret.Length - 1
If ActiveControl.Text = Mot.MotSecret(j) Then
Mot.LettreDecouverte(j) = Mot.MotSecret(j)
End If
Next j
Label1.Text = ""
For j = 0 To Mot.MotSecret.Length - 1
Label1.Text = Label1.Text + " "
If Mot.LettreDecouverte(j).Equals("") Then
Label1.Text = Label1.Text + "_"
Else
Label1.Text = Label1.Text + Mot.LettreDecouverte(j)
End If
Next j
End Sub
Private Sub JouerToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles JouerToolStripMenuItem.Click
GenereMot()
End Sub
Private Sub Pendu_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
GenereMot()
End Sub
Function GenereMot()
Dim NbItems As Integer
Dim Aleatoire As New Random()
Dim NbAleatoire As Integer
ListBox1.Items.AddRange(System.IO.File.ReadAllLines("listemot.txt"))
NbItems = ListBox1.Items.Count
NbAleatoire = Aleatoire.Next(NbItems)
Mot.MotSecret = ListBox1.Items(NbAleatoire)
Return Mot
End Function
End Class

the Mot.LettreDecouverte can be Nothing i.e. not initialized as you don't set any value for it.
This can cause error to happen both in Mot.LettreDecouverte(j) = Mot.MotSecret(j) line and also in If Mot.LettreDecouverte(j).Equals("") Then... line of your code.
change your ButtonA_Click event handler code as following:
i = i + 1
ActiveControl.Visible = False
PictureBox1.Image = ImageList1.Images(i - 1)
Dim j As Integer = 0
If Mot.LettreDecouverte Is Nothing OrElse Mot.LettreDecouverte.Length < Mot.MotSecret.Length Then
Mot.LettreDecouverte = Space(Mot.MotSecret.Length) '* initiate it by enough number of space chars
End If
For j = 0 To Mot.MotSecret.Length - 1
If ActiveControl.Text = Mot.MotSecret(j) Then
Mot.LettreDecouverte(j) = Mot.MotSecret(j)
End If
Next j
Label1.Text = ""
For j = 0 To Mot.MotSecret.Length - 1
Label1.Text = Label1.Text + " "
If Mot.LettreDecouverte(j).Equals(" "c) Then '*Note: i use space char, not empty string
Label1.Text = Label1.Text + "_"
Else
Label1.Text = Label1.Text + Mot.LettreDecouverte(j)
End If
Next j
Note that the value of Mot.LettreDecouverte(j) is always a char and a char can not be an empty string as you typed in Mot.LettreDeciouverte(j).Equals(""). i initiate the LettreDeciouverte with an array of space chars such that we can check its elements comparing against " "c char.

Related

Using vb.net Count all occurrences of vbCrLf in TextBox

I have a TextBox that I am trying to count all the occurrences of vbCrLf.
The counting is working, the issue is every time a vbCrLf is issued I would like to subtract 33 from some Integer.
The code as written now only subtracts the number of vbCrLf, NOT the number + 33.
Question is how to subtract 33 every time the Enter Key is pressed and a vbCrLf is issued ?
I have posted Updated Code The Question Was Answered and Issues SOLVED
I have also added additional code that enhances the management of the TextBox
You will need these Imports
Imports System.IO
Imports System.Text
Public Class frmThree
Dim path As String = "C:/Users/Me/source/repos/TestForms/TestForms/Resource/"
Dim total As Integer
Dim vbLfTotal As Integer
Dim chrPermited As Integer = 333 'chrPermited
Private Sub btnBack_Click(sender As Object, e As EventArgs) Handles btnBack.Click
Me.Close()
frmOne.Show()
End Sub
Private Sub tbHaveOne_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbHaveOne.TextChanged
Dim spaceCount, letterCount, carReturn As Integer
spaceCount = 0
letterCount = 0
carReturn = 0
Dim str As String = tbHaveOne.Text
For Each chr As Char In str
If chr = vbLf Then
carReturn += 1
ElseIf Char.IsLetterOrDigit(chr) Then
letterCount += 1
ElseIf Char.IsWhiteSpace(chr) Then
spaceCount += 1
End If
Next
vbLfTotal = carReturn * 29
total = chrPermited - letterCount - spaceCount - vbLfTotal
tbHaveTwo.ForeColor = Color.Black
tbHaveTwo.Text = total & " More Character Can Be Entered"
While total < 10
tbHaveTwo.Clear()
tbHaveTwo.ForeColor = Color.Red
tbHaveTwo.Text = "Only " & total & " More Character Can Be Entered"
Exit While
End While
If total = 5 Then
PlaySystemSound()
End If
If total < 1 Then
tbHaveTwo.Clear()
tbHaveTwo.Text = "No More Data Entry" & total
Call ansQ()
End If
End Sub
Sub PlaySystemSound()
My.Computer.Audio.PlaySystemSound(
System.Media.SystemSounds.Hand)
End Sub
Public Sub ansQ()
Const Msg As String = "YES Save Data" + vbCrLf + vbNewLine + "NO CANCEL"
Const Title As String = "Save or Exit"
Const Style = vbYesNo + vbQuestion + vbDefaultButton2
Dim result = MsgBox(Msg, Style, Title)
If result = vbYes Then
Call writeDATA()
ElseIf result = vbNo Then
'tbHaveOne.ReadOnly = True
'tbHaveOne.Enabled = False
tbHaveTwo.Text = "NO Was Selected"
'result = 0
End If
End Sub
Public Shared Sub tbHaveOne_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles tbHaveOne.KeyDown
'NOTE this Sub is Shared It seems to run all the time like a listener
If e.KeyCode = Keys.Enter And frmThree.total < 40 Then
e.SuppressKeyPress = True
End If
End Sub
The TextBox.Lines.Count returns the count of the lines separated by newline characters (ControlChars.NewLine or Environment.NewLine when you hit the Enter key.) and not the count of the word-wrapped lines in a multiline TextBox. If you set the WordWrap property to False you will see the difference. See the TextBoxBase.Lines remarks section.
You could call the SendMessage method and the EM_GETLINECOUNT message if you need to get the count of the lines regardless whether they are word-wrapped or separated new lines:
Imports System.Runtime.InteropServices
Private Const EM_GETLINECOUNT As UInteger = &HBA
<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr,
ByVal msg As Integer,
ByVal wp As IntPtr,
ByVal lp As IntPtr) As IntPtr
End Function
Private Sub PrintCounts()
Dim c = tbHaveOne.Text.
Aggregate(New With {
.WhiteSpaces = 0, .Lf = 0, .NewLines = 0, .Lines = 0, .Others = 0
},
Function(x, y)
x.Lf += If(y = ControlChars.Cr, 1, 0)
x.WhiteSpaces += If(Char.IsSeparator(y), 1, 0)
x.Others += If(Not Char.IsWhiteSpace(y), 1, 0)
Return x
End Function)
c.NewLines = tbHaveOne.Lines.Count
c.Lines = SendMessage(tbHaveOne.Handle, EM_GETLINECOUNT,
IntPtr.Zero, IntPtr.Zero).ToInt32
tbHaveTwo.Text = $"WhiteSpaces: {c.WhiteSpaces} Lf: {c.Lf} " +
$"New Lines: {c.NewLines} Lines {c.Lines} Others: {c.Others}"
End Sub
Private Sub tbHaveOne_TextChanged(sender As Object,
e As EventArgs) Handles tbHaveOne.TextChanged
PrintCounts()
End Sub
Please note:
The Char.IsSeparator method is used to get the count of the white spaces since the Char.IsWhiteSpace method will return True when evaluating; vbCr, vbLf, vbCrLf, vbTab, ...etc. Alternatively, you can combine the Char.IsWhiteSpace and the Char.IsControl methods to evaluate the white spaces. The Remarks section has more.
The Others is the count of everything else including the letters, digits, punctuations, symbols...etc. You may wont to examine the other Char.IsXXX methods of the Char structure.
Check out the values of the Lines and NewLines fields as you type.
You can't check if the current character is vbcrlf because CRLF is two characters. Just check for the LF, this way if you ever use the logic on a file prepared by a unix system, it still works (unix has LF, Windows has CRLF)
Private Sub tbHaveOne_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbHaveOne.TextChanged
Dim spaceCount = 0
Dim letterCount = 0
Dim lineCount = 0
For Each c As Char In tbHaveOne.Text
If c = vbLf Then
lineCount += 1
ElseIf Char.IsLetterOrDigit(c) Then
letterCount += 1
ElseIf Char.IsWhiteSpace(c) Then
spaceCount += 1
End If
Next c
someInteger -= (lineCount * 33)
The System.Char has static methods that check characters are in certain Unicode ranges - for your letter count you were counting anything that wasn't a space, including carriage returns, punctuation and other things that aren't letters, as letters. You're free to carry on doing that if you want but it'll maybe lead to a bit of a confusing count if you triple count the newlines
The counting is working the issue is every time a vbCrLf is issued I would like to subtract 33 from some Integer
The code as written now only subtracts the number of vbCrLf NOT the number + 33
I didn't quite get this. You say you want to subtract 33 every time there is a new line, which is what I've done. The second sentence reads like the requirement is to subtract the (number of new lines + 33) from someInteger. If this is what you want to do, change the * on the last line to +
Question is how to subtract 33 every time the Enter Key is pressed and a vbCrLf is issued ?
This is a different thing entirely to "count all occurrences of"; it isn't to do with counting the lines in a textbox, and you can't do it from such code. Counting the number of times the user has ever pressed enter in a textbox needs a hook to the event raised when a user pressed a key while the box had focus. Add a handler for the KeyPress or KeyDown event:
Private Sub tbHaveOne_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles tbHaveOne.KeyPress 'KeyEventArgs for KeyDown event
If e.KeyChar = vbCr Then 'use e.KeyCode = Keys.Enter in KeyDown event
someInteger -= 33
End If
End Sub
We have a lot of great Discussion and Fixed Answers on this question
One of the questions in the discussion was how to handle punctuation and special characters
We would like to offer this code as a way to manage both punctuation and special characters
Dim spaceCount, letterCount, carReturn, punCount, syCount As Integer
spaceCount = 0
letterCount = 0
carReturn = 0
punCount = 0
syCount = 0
Dim str As String = tbHaveOne.Text
For Each chr As Char In str
If chr = vbLf Then
carReturn += 1
ElseIf Char.IsLetterOrDigit(chr) Then
letterCount += 1
ElseIf Char.IsWhiteSpace(chr) Then
spaceCount += 1
ElseIf Char.IsPunctuation(chr) Then
punCount += 1
ElseIf Char.IsSymbol(chr) Then
syCount += 1
End If
Next
vbLfTotal = carReturn * 29
total = chrPermited - letterCount - spaceCount - vbLfTotal - punCount - syCount
tbHaveTwo.ForeColor = Color.Black
tbHaveTwo.Text = total & " More Character Can Be Entered"

I get an error when calling a textbox from form1

I'm having issues with this:
I have this code on Form2:
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lbl0, lbl1, lbl11, lbl2, lbl22, lbl3, lbl33, lbl4, lbl44, lbl5, lbl55, lbl6, lbl66, lbl7, lbl77 As New Label
lbl0.Text = "ACCESORIOS"
lbl0.Font = New System.Drawing.Font("MS Reference Sans Serif", 15.75, FontStyle.Bold)
lbl0.Location = New Point(110, 12)
lbl0.AutoSize = True
Me.Controls.Add(lbl0)
lbl1.Text = "Té 180°"
lbl11.Text = Te180
lbl2.Text = "Té 90° Empalme - Codo Triple"
If form1.TextBox3.Text <> 0 Then
lbl22.Text = 0
Else
lbl22.Text = (Int(form1.TextBox1.Text) + Int(form1.TextBox2.Text)) - 1
End If
lbl3.Text = "Soporte 90° T/T"
lbl33.Text = SoporteTT90
TableLayoutPanel1.Controls.Add(lbl33, 0, 0)
End Sub
End Class
Don't mind the variables not used, or the single tablelayoutpannel adding, since it's a work in progress. Anyway, this code works well the first time I run it, but when I press reset,
which is a button in form1 that contains this piece of code:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim frm = New form1
frm.Show()
Me.Close()
Te180 = 0
ContadorGlobal = 0
SoporteTT90 = 0
End Sub
I end up with this error:
An unhandled exception of type 'System.InvalidCastException' occurred
in Microsoft.VisualBasic.dll
Additional information: Conversion from string "" to type 'Double' is not valid.
I get that when the program goes through here:
If form1.TextBox3.Text <> 0 Then
lbl22.Text = 0
Else
lbl22.Text = (Int(form1.TextBox1.Text) + Int(form1.TextBox2.Text)) - 1
End If
Any help is appreciated. Many I'm not calling form1.textbox1.text correctly. Maybe I'm not resetting it properly. I have no idea since I'm not an expert. Thanks in advance!
Text property of Textboxes and Labels are of type String.
Assuming that form1.TextBox1.Text and form1.TextBox2.Text contains integer values, you're setting an arithmethic operation result to lbl22.Text which should contain a string, not a number.
Change
lbl22.Text = (Int(form1.TextBox1.Text) + Int(form1.TextBox2.Text)) - 1
By
lbl22.Text = ((Int(form1.TextBox1.Text) + Int(form1.TextBox2.Text)) - 1).ToString
Said that, the error Conversion from string "" to type 'Double' is not valid is telling you that an empty string cannot be converted to a number, so be sure both TextBox1.Text and TextBox2.Text are not empty prior to perform the arithmetic operation.

label loop for next visual basic

Currently my code looks like this:
Private Sub btnMotivate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMotivate.Click
Dim intNumber As Integer
Dim strStudy As String = "Study!"
intNumber = InputBox("How many times do you want to be motivated? Please use numbers!")
If intNumber < 1 Then
MessageBox.Show("Please use a number from 1 - 10!")
End If
If intNumber > 10 Then
MessageBox.Show("Please use a number from 1 - 10!")
End If
> For intCounter = 1 To intNumber Step 1
lblMotivation.Text = strStudy
> Next
End Sub
As you can see, I have added a variable and the loop runs fine, but I need help phrasing the code so whatever number the user inputs, is the number of lines of "Study!" displayed. I have tried using the string but also using the label with Environment.NewLine hoping it would add a new line every time the loop runs
You are setting the label text to strStudy each time. This doesn't add to what's there already, it just replaces it.
You need to add strStudy to the text that already exists, something like this:
' start with an empty string
lblMotivation.Text = ""
For intCounter = 1 To intNumber Step 1
' append the study string and a newline
lblMotivation.Text = lblMotivation.Text & strStudy & Environment.NewLine
Next
Instead of using a TextBox, use a ListBox to display the word Study! n -times. It is also good practice not to instruct the user to do something, but prevent it in code. Also note how intNumber has been changed to *inp*Number As Object
Private Sub btnMotivate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMotivate.Click
Dim inpNumber As Object
Dim strStudy As String = "Study!"
Dim intCounter As Integer
inpNumber = InputBox("How many times do you want to be motivated?")
If Not IsNumeric(inpNumber) Then
MessageBox.Show("Please enter a number!")
ElseIf inpNumber < 1 OrElse inpNumber > 10 Then
MessageBox.Show("Please enter a number from 1 - 10!")
Else
ListBox1.Items.Clear()
For intCounter = 1 To inpNumber Step 1
ListBox1.Items.Add(strStudy)
Next
End If
End Sub

Moving through datagridview rows on keypress

I'm trying to go through datagridview rows where the cell value starts with the same keychar the user pressed. Code bellow works, but It wont move selection to next row starting with same letter when I press same letter second, third time...
Private Sub dataGridView1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles dgw.KeyPress
If [Char].IsLetter(e.KeyChar) Then
For i As Integer = 0 To (dgw.Rows.Count) - 1
If dgw.Rows(i).Cells(1).Value.ToString().StartsWith(e.KeyChar.ToString(), True, CultureInfo.InvariantCulture) Then
If lastKey = e.KeyChar And lastIndex < i Then
Continue For
End If
lastKey = e.KeyChar
lastIndex = i
dgw.Rows(i).Cells(1).Selected = True
Return
End If
Next
End If
End Sub
Seems like a flaw in the logic. You press key, save index and break. Then you press the same key. And if lastIndex is lesser than i you continue. Which means it will only select the first row it finds with a lesser value than the last one. Change to lastindex > i and you should be fine.
You can with the code you have written never get anything else than the first line matching the key. After that it doesn't matter how many times you press.
I know that is too old this post... anyway I've found a workaround for this and maybe it will be useful for someone.
public lastkey as string
Private Sub dataGridView1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles dgw.KeyPress
Dim input = StrConv(e.keychar.toString()
lastkey += input
Dim found as Boolean
if StrConv(dgw.currentCell.Value.toString.Substring(0,1), VbStrConv.UpperCase) = input then
dim curIndex = dgw.currentRow.Index
if curIndex < dgw.rows.count - 1 then
dgw.ClearSelection()
curIndex += 1
dgw.currentCell = dgw.rows(curIndex).Cells(0)
dgw.rows(curIndex).selected = true
end if
else
dgv_jumpRecord(lastkey,found)
if not found then
lastkey = input
dgv_jumpRecord(lastkey,found)
end if
End if
End Sub
Public Sub dgv_jumpRecord(byVal lastkey as String, ByRef found as boolean)
For i As Integer = 0 To (dgw.Rows.Count) - 1
dim rowText = dgw.Rows(i).Cells(1).Value.ToString
If StrConv(rowText.ToString(),VbStrConv.UpperCase).StartsWith(lastkey) Then
dgw.ClearSelection()
dgw.CurrentCell = dgw.rows(i).Cells(0)
dgw.rows(i).selected = true
found = true
Exit Sub
End If
Next
found = false
End Sub

autocomplete text box for .net with support for delimiter

I am developing an application which requires a text box with auto-complete/suggestions (drop down) for multiple words (separated by a delimiter like space) like the tags text box here in StackOverflow.
For example, I start typing 'app' and it should show all words in the suggestions list starting with app, and when I enter a word and press space and start typing a new word it should show all suggestions for that partial word.
Is there an example I can have a look at?
I Hope this helps.. I'm using developer-express tools, but the same can be used with the regular .net components.
Private Sub txtToEmail_EditValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtToEmail.EditValueChanged
Try
Dim Emails As New List(Of String)
Emails.Add("123#abc.com")
Emails.Add("456#dfg.com")
Emails.Add("abc#123.com")
Emails.Add("dfg#456.com")
Dim Txt = Trim(CStr(txtToEmail.EditValue))
Dim Suggestions As IEnumerable(Of String)
If Txt <> "" Then
If Txt.IndexOf(",") = -1 Then
Suggestions = From c In Emails Where c.StartsWith(Txt) Select c
Else
Dim lastIndex = Txt.LastIndexOf(",")
Dim lastWord = Trim(Txt.Substring(lastIndex + 1))
Suggestions = From c In Emails Where c.StartsWith(lastWord) Select c
End If
EmailList.Items.Clear()
For Each r In Suggestions
EmailList.Items.Add(r)
Next
End If
If EmailList.ItemCount > 0 Then
EmailList.Visible = True
End If
Catch ex As Exception
ShowErrorBox(ex)
End Try
End Sub
Private Sub EmailList_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles EmailList.Click
Try
If EmailList.SelectedValue = Nothing OrElse EmailList.SelectedValue = "" Then Return
Dim Txt = CStr(txtToEmail.EditValue)
If Txt.IndexOf(",") = -1 Then
txtToEmail.EditValue = EmailList.SelectedValue
Else
Dim lastIndex = Txt.LastIndexOf(",")
txtToEmail.EditValue = Txt.Substring(0, lastIndex + 1) & EmailList.SelectedValue
End If
txtToEmail.Focus()
txtToEmail.SelectionStart = CStr(txtToEmail.EditValue).Length
EmailList.Visible = False
Catch ex As Exception
ShowErrorBox(ex)
End Try
End Sub