Find and Replace using another form - vb.net

I have my frmMainwhich has RichTextBox1 and I have a button btnfind&Replacewhich whose click event pops out another minute form frmFindandReplace which has two textboxes: TextBoxSearch and TextBoxReplace with two buttons: replaceButton and findButton. I cannot seem to get my code for instances of finding a word in textbox and an instance of replacing it. Here is my code:
Public Class frmFindandReplace
Dim txtClientArea As RichTextBox
Private Sub TextBoxSearch_TextChanged(sender As Object, e As EventArgs) Handles TextBoxSearch.TextChanged
End Sub
Private Sub frmFindandReplace_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub replaceButton_Click(sender As Object, e As EventArgs) Handles replaceButton.Click
End Sub
Protected Friend Sub findButton_Click(sender As Object, e As EventArgs) Handles findButton.Click
Dim a As String
Dim b As String
a = TextBoxSearch.Text
b = InStr(StartPosition, a, txtClientArea)
If b Then txtClientArea.Focus()
txtClientArea.SelectionStart = b - 1
txtClientArea.SelectionLength = Len(a)
txtClientArea.ScrollToCaret()
End Sub
The findButton code doesnot even work. Throws an error!
Error 3: Overload resolution failed because no accessible 'InStr' can be called with these arguments:
'Public Function InStr(Start As Integer, String1 As String, String2 As String, [Compare As Microsoft.VisualBasic.CompareMethod = Microsoft.VisualBasic.CompareMethod.Binary]) As Integer': Value of type 'System.Windows.Forms.TextBox' cannot be converted to 'String'.
'Public Function InStr(String1 As String, String2 As String, [Compare As Microsoft.VisualBasic.CompareMethod = Microsoft.VisualBasic.CompareMethod.Binary]) As Integer': Value of type 'System.Windows.Forms.RichTextBox' cannot be converted to 'Microsoft.VisualBasic.CompareMethod'. C:\Users\Joseph GodwinKE\Documents\Visual Studio 2013\Projects\simpleapp\frmFindandReplace.VB 25 13 Simple app
I know I have not done much but am new and all my efforts of searching a solution over the internet have failed! Thank you I hope someone will help me pls.

A few pointers:
InStr returns an integer.
Check the documentation as it'll show you have the search values the wrong way around.
Turn Option Explicit on to help find your issues.
This should work better.
Private Sub findButton_Click(sender As Object, e As EventArgs) Handles findButton.Click
Dim searchString As String
Dim findPos As Integer
Try
searchString = TextBoxSearch.Text
findPos = InStr(txtClientArea.Text, searchString)
If findPos > 0 Then txtClientArea.Focus()
txtClientArea.SelectionStart = findPos - 1
txtClientArea.SelectionLength = searchString.Length
txtClientArea.ScrollToCaret()
Catch ex As Exception
MessageBox.Show(String.Concat("An error occurred: ", ex.Message))
End Try
End Sub

If you want your code work you need to pass the reference to the RichTextBox present in the first form to the findandReplace form.
Otherwise you will not be able to work with that instance of the RichTextBox.
Usually, this means that when you create and open an instance of the findandReplace form you pass the reference to the RichTextBox to work with in the call to the constructor. Something like this
Dim fReplace As frmFindandReplace = New frmFindandReplace(Me.txtClientArea)
fReplace.Show()
Here the New call reaches the constructor of frmfindandReplace. This call is usually hidden by VB.NET but you could add it writing explicit code for it
Public Class frmFindandReplace
Dim txtClientArea As RichTextBox
Public Sub New (ByVal txt as RichTextBox)
txtClientArea = txt
End Sub
Now the global variable txtClientArea inside the findandReplace class is assigned to the existing reference of the RichTextBox present in the first form and you could happily work with it
Protected Friend Sub findButton_Click(sender As Object, e As EventArgs) Handles findButton.Click
Dim a As String
a = TextBoxSearch.Text
Dim position = txtClientArea.Find(a, 0, RichTextBoxFinds.MatchCase)
.....
End Sub
And please make yourself a favor and start using the more complete methods available from the NET Framework library and stop using the old fashioned VBA methods.
For example the RichTextBox has a method that does exactly what you are trying to do in code. Find, search the content of the textbox and if it founds a match it highlight the text and return the starting position of the text.
There is no replace builtin method but having the position and the length is really simple to implement your own replacing code.

You Have defined b as a string. Change it to an integer. Also Instr doesn't allow you to set a start position, just a string to search and the string to search for and optionally the type of search - Binary or Text.
Finally rather than type If b then, use If b>0 then rather than turning off Option Strict. It's always better to write code with Option Strict on as it makes you write better code and in the long run is easier to chase down errors

Related

User enters letter then button computes position from a string using VB

I am using indexOf but I cannot figure out where I made a mistake as the output gives a -1.
I realise I can copy the whole statement paragraph into the last line of the output but I was hoping it could pull it straight from the label.
Public Class Form1
Private Sub btnCompute_Click(sender As Object, e As EventArgs) Handles btnCompute.Click
Dim statement As String
Dim letter As String
statement = CStr(lblStatement.Text)
letter = CStr(txtLetter.Text)
txtOutput.Text = CStr(lblStatement.Text).IndexOf("letter")
'txtOutput.Text = letter.ToUpper & " first occurs in position " & statement.IndexOf(statement) & "."
End Sub
End Class
Here is a picture of the form:
Update: Thanks to #ADyson and #Slugsie for taking the time to respond to my call for help. As #Slugsie noted it was indeed down to the lower case in my screenshot. I am now researching how to make it work without being case-sensitive.
Final code
Public Class Form1
Private Sub btnCompute_Click(sender As Object, e As EventArgs) Handles btnCompute.Click
txtOutput.Text = lblStatement.Text.IndexOf((txtLetter.Text).ToUpper)
End Sub
End Class
.IndexOf("letter")
is looking for the literal text letter within the data the user enters in the text. in VB.NET (and most other programming languages), anything enclosed within quote marks is treated as a fixed string of text, to be interpreted as-is rather than processed or treated as program code.
To make it look for the contents of the letter variable instead (which looks like what you were intending) simply remove the quote marks:
.IndexOf(letter)
As an aside, your whole code could be much reduced - primarily the use of CStr is unnecessary, because the Text properties of the textbox and label already return a string - meaning you don't need to use CStr convert it - and also because you're not making use of all the variables you declared either.
You could re-write your whole sample much more succinctly as:
Public Class Form1
Private Sub btnCompute_Click(sender As Object, e As EventArgs) Handles btnCompute.Click
txtOutput.Text = lblStatement.Text.IndexOf(txtLetter.Text)
End Sub
End Class

How to fix System.FormatException: 'Input string was not in a correct format'

I am trying to change Font Family in VB.NET for a RichTextBox
I have tried searching through google and even specific sites for just code problems. Nothing works.
These are the codes for FontFamily changing (it is a tool strip combo button)
Private Sub TscFontFamily_TextChanged(sender As Object, e As EventArgs) Handles tscFontFamily.TextChanged
rtbContent.SelectionFont = New Font(Convert.ToString(tscFontFamily.Text), Convert.ToInt32(tscFontSize.Text))
End Sub
And the FontSize (also a tool strip combo button)
Private Sub tscFontSize_TextChanged(sender As Object, e As EventArgs) Handles tscFontSize.TextChanged
Dim newSize As Single = Convert.ToSingle(tscFontSize.Text)
rtbContent.SelectionFont = New Font(rtbContent.SelectionFont.FontFamily, newSize)
End Sub
I expect this to work since it makes sense, right? But it says "input string was not in correct format" and if i remove the Convert.ToString and other convert code, it says something like "Conversion from string "" to type 'Single' is not valid.".
Also to mentiion, is the fact that i have actually tried Convert.ToString and Convert.ToDouble and basically everything for BOTH.
There is no need to call ToString on tscFontFamily.Text because the Text property of a TextBox returns a String; you're essentially saying return a String value from this String value.
Convert.ToInt32 is a quick and dirty was of converting String values to Int32 (aka integer) values. If you're relying on input from a user then you should almost always use Int32.TryParse instead. This method returns a Boolean value based on if the conversion of the input is successful and then the second parameter passed is a reference variable so if the result of the method is True then the second parameter contains the converted value. However, it looks like you're wanting a Single value in which case you'd actually use Single.TryParse.
Here would be an example applying the changes to your code:
Private Sub tscFontSize_TextChanged(sender As Object, e As EventArgs) Handles tscFontSize.TextChanged
Dim newSize As Single
If Single.TryParse(tscFontSize.Text, newSize) Then
rtbContent.SelectionFont = New Font(rtbContent.SelectionFont.FontFamily, newSize)
End If
End Sub

How to check a text box for a certain character and replace with a different string in the same spot

I am working on a little morse code translation project and I cannot figure out how to detect when a certain key is in a textbox and replace it with the corresponding morse code dots and dashes in the correct spot.
For example if you type in "a b c" then i would like the program to check and put
".- -... -.-."
but it also needs to be dynamic so if you change up the order of your letters it can update the translation.
as of right now i have a key checking system where you can only type in one forward line and if you mess up you have to clear the whole box. thank you!
Here is a basic example of what I was suggesting in my comments above, i.e. using two separate TextBoxes and translating the whole text every time:
Private morseCodeDictionary As New Dictionary(Of Char, String) From {{"a"c, ".-"},
{"b"c, "-..."},
{"c"c, "-.-."}}
Private Sub inputTextBox_TextChanged(sender As Object, e As EventArgs) Handles inputTextBox.TextChanged
outputTextBox.Text = String.Join(" ",
inputTextBox.Text.
ToLower().
Select(Function(ch) morseCodeDictionary(ch)))
End Sub
Here's an implementation that doesn't use LINQ, so may be more understandable:
Private Sub inputTextBox_TextChanged(sender As Object, e As EventArgs) Handles inputTextBox.TextChanged
Dim characterStrings As New List(Of String)
For Each ch As Char In inputTextBox.Text
characterStrings.Add(morseCodeDictionary(ch))
Next
outputTextBox.Text = String.Join(" ", characterStrings)
End Sub

How To Evaluate a String Containing References to Windows Forms Controls At Runtime?

How can you, in VB.Net, evaluate the value of controls referenced in a string? Suppose you have a textbox N containing some alphanumeric content and it were referenced in a string variable like this:
Dim s As String = """Hello "" & N.Text & ""!"""
I'd like to be able to reevaluate the contents of the s variable elsewhere in the code (where there's no direct knowledge of the existence of N), for example, like this:
Dim e As String = Eval(s)
This isn't possible with VB.Net; no such Eval function is available. I've seen some nearly plausible solutions online such as using the old COM ScriptControl:
Private Shared _scriptControl As MSScriptControl.ScriptControl = New ScriptControl()
_scriptControl.Language = "VBScript"
Dim e As String = _scriptControl.Eval(s)
However, the reference to the N.Text property of a Windows Forms control is alien to the ScriptControl object, and therefore it throws an error.
Is there any other quick fix that won't require the purchase of a third-party component?
However, the reference to the N.Text property of a Windows Forms
control is alien to the ScriptControl object, and therefore it throws
an error. ... I only mentioned the ScriptControl idea to fend off
answers that might involve that approach I mentioned since I already
tried it and don't want to waste our time.
You can add the TextBox to the Script Control. First, get a reference to "N" using it's Name. Not sure if you've got the name of the control by itself already; if not, you may need to parse your string to get the name. Then use Controls.Find() to get a reference and pass that to AddObject(). Now your string can be evaluated as expected:
Private Shared _scriptControl As MSScriptControl.ScriptControl = New ScriptControl()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
_scriptControl.Language = "VBScript"
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim ctlName As String = "N"
Dim ctl As Control = Me.Controls.Find(ctlName, True).FirstOrDefault
If Not IsNothing(ctl) Then
Try
_scriptControl.AddObject(ctlName, ctl)
Catch ex As Exception
End Try
Dim code As String = """Hello "" & N.Text & ""!"""
Dim result As String = _scriptControl.Eval(code)
MessageBox.Show(result)
End If
End Sub
String Interpolation was introduced in Visual Basic 14. Since the control is declared as a Friend variable in the Form's designer, then presumably you could use the reference to the control in the String like this:
Dim s As String = $"Hello {N.Text}!"

VB.NET WebBrowser Control Programmatically Filling Form After Changing User-Agent (Object reference not set to an instance of an object.)

I'm working on a project where I have a WebBrowser control which needs to have a custom user-agent set, then go to Google and fill out the search box, click the search button, then click a link from the search results. Unfortunately I can't use HTTPWebRequest, it has to be done with the WebBrowser control.
Before I added the code to change the user-agent, everything worked fine. Here's the code that I have:
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("urlmon.dll", CharSet:=CharSet.Ansi)> _
Private Shared Function UrlMkSetSessionOption(dwOption As Integer, pBuffer As String, dwBufferLength As Integer, dwReserved As Integer) As Integer
End Function
Const URLMON_OPTION_USERAGENT As Integer = &H10000001
Public Sub ChangeUserAgent(Agent As String)
UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, Agent, Agent.Length, 0)
End Sub
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
ChangeUserAgent("Fake User-Agent")
wb.Navigate("http://www.google.com", "_self", Nothing, "User-Agent: Fake User-Agent")
End Sub
Private Sub wb_DocumentCompleted(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs) Handles wb.DocumentCompleted
Dim Source As String = wb.Document.Body.OuterHtml
Dim Uri As String = wb.Document.Url.AbsoluteUri
If Uri = "http://www.google.com/" Then
wb.Document.GetElementById("lst-ib").SetAttribute("value", "browser info")
wb.Document.All("btnK").InvokeMember("click")
End If
If Uri.Contains("http://www.google.com/search?") Then
Dim TheDocument = wb.Document.All
For Each curElement As HtmlElement In TheDocument
Dim ctrlIdentity = curElement.GetAttribute("innerText").ToString
If ctrlIdentity = "BROWSER-INFO" Then
curElement.InvokeMember("click")
End If
Next
End If
End Sub
End Class
The problem lies in the following code:
wb.Document.GetElementById("lst-ib").SetAttribute("value", "browser info")
wb.Document.All("btnK").InvokeMember("click")
I thought the problem might be that the page not being fully loaded (frame issue) but I put the offending code in a timer to test, and got the same error. Any help would be much appreciated.
Do you realize .All("btnK") returns a collection? So, you are doing .InvokeMember("click") on a Collection :). You cannot do that, you can only do .InvokeMember("click") on an element for obvious reasons!
Try this:
wb.Document.All("btnK").Item(0).InvokeMember("click")
The .Item(0) returns the first element in the collection returned by .All("btnK"), and since there will only probably be one item returned, since there is only one on the page, you want to do the InvokeMember on the first item, being .Item(0).
May I ask what it is you are developing?
Since you're a new user, please up-vote and/or accept if this answered your question.