Windows Forms RichTextBox - Event driven by the word clicked on - c#

I am building a c# win forms application. The application reads an IRC channel and displays the messages that are going through. These messages are displayed like:
{username}: {message that posted or action performed}
I need it so that the user of an application can click on a username (these are stored in array and so can be referenced) another modal form opens with the username passed in. The trouble is, I have no idea how to detect which word in the RichTextBox was clicked on (or even if that is possible).
Any help will be greatly appreciated. I really am at a dead end and other than code that detects a highlighted selection I am no where.
Regards,
Chris

The only solution I could find is to use the RichTextBox method GetCharIndexFromPosition and then perform a loop outward from there, stopping at each end for anything non-alphabetic.
private void richTextBox1_MouseClick(object sender, MouseEventArgs e)
{
int index = richTextBox1.GetCharIndexFromPosition(e.Location);
String toSearch = richTextBox1.Text;
int leftIndex = index;
while (leftIndex < toSearch.Count() && !Char.IsLetter(toSearch[leftIndex]))
leftIndex++; // finds the closest word to the right
if (leftIndex < toSearch.Count()) // did not click into whitespace at the end
{
while (leftIndex > 0 && Char.IsLetter(toSearch[leftIndex - 1]))
leftIndex--;
int rightIndex = index;
while (rightIndex < toSearch.Count() - 1 && Char.IsLetter(toSearch[rightIndex + 1]))
rightIndex++;
String word = toSearch.Substring(leftIndex, rightIndex - leftIndex + 1);
MessageBox.Show(word);
}
}
In your situation, you may have usernames with numbers or spaces and might want to stop the rightIndex when it hits a colon. If the username is always at the start of a newline, you may also want to stop the leftIndex at newlines ('\n').

Related

Why doesn't my counter count?

This really suprised me. One of the simplest things doesn't work, making a counter. I'm making a kinda game application in c# and there is also a timer who counts the time. Very simple right? I know how to code this and this is something I did before but I don't understand why it isn't working now.
int i = 0;
i++;
label1.Text = i.ToString();
label1.Text turns in to 1 and nothing else happens. Also tryied this with a timer but it freeezes in 1. I know this post isn't really going to help other people but it is very frustrating.
Why you are always getting 1 in your label1 text?
The reason is very simple, each time you are getting to the first line, i is 0:
// Line 1
int i = 0; // declaring and setting i to 0
// Line 2
i++; // incrementing i to 1
// Line 3
label1.Text = i.ToString(); // displaying i (which is equal to 1)
and then again you are getting to the Line 1 and setting i=0, etc...
I presume you have a UI application (win form, web form etc...)
You already mentioned you have a timer that works fine and a label where you output the incremented i variable.
As already commented in order to see a change in your label you can use a loop as following:
int length = 100; // for example
for (int i = 0; i < length; i++)
{
label1.Text = i.ToString();
}
The output in label1 text will be 0, then 1, then 2 .... and finally 99.
Obviously you won't be able to see all those values except the last one 99 at run-time but you can debug and see how it works.
I presume, what you needed is to have your label text changing each time the timer will tick.
Following a code example how you could implement it:
private int i = 0; // initialized once in this UI class
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = i.ToString();
i++; // will increment by one each time the timer is ticking
}
Set your timer interval to ~1000 so you could clearly see how your text label increments at run-time.
If you want to increment it you have to add the incrementing logic in a loop like for or while loop:
If you want to use timer to count something please refer to this question : here

C#: Auto text highlight in RichText

I am extremely very new to C#, just wrote some calculator, text editors and DB client in the school almost 10 years ago :) Not I am trying to make a tool for myself and my colleagues to view traces and logs in easier way. All we know Notepad++, we used daily for text highlighting, styling, but the thing is that these highlights get lost after you close Notepad++.
So my goal now is to make the same text editor but so it will be able to save your work.Currently I am working on the feature so when I am selecting some text, it will search for the same on whole document and highlight it, for example with red background. I added this one:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
int startIndex = 0;
while (startIndex<richTextBox1.TextLength)
{
int wordStartIndex = richTextBox1.Find(richTextBox1.SelectedText, startIndex, RichTextBoxFinds.None);
if (wordStartIndex != -1)
{
richTextBox1.SelectionStart = wordStartIndex;
richTextBox1.SelectionLength = richTextBox1.SelectionLength;
richTextBox1.SelectionBackColor = Color.Red;
}
else
break;
startIndex += wordStartIndex + richTextBox1.SelectionLength;
}
}
But it gives me "StackOverFlow" as I have a loop here. Can you please assist me with it?
I think I need to run 2 searches to avoid loop - one before selection index, one after. Or maybe there is easier option?
Thank you all, guys!
You're getting an infinite loop because you're in an event that checks for a selection change, and then in that event, you're changing the selection, which causes an event, where you change the selection, which causes an event...
If you want to avoid this you'll need a class level variable like
bool inSelectionChangeEvent;
and then change your code to:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
if (!inSelectionChangeEvent){
inSelectionChangeEvent = true;
}
else{
return;
}
...
Also, you're writing your OWN text editor? Err, there may be a simpler solution :)
Your problem is with the selection length. Right here:
richTextBox1.SelectionLength = richTextBox1.SelectionLength;
It does no good to set something equal to itself and I'm guessing this was an accident. When the SelectionLength is 0, startIndex never increases (anything + 0 is anything).
The first thing I'd do is check if richTextBox1.SelectionLength < 1 and if it is, just return from the method without doing anything.
This code snippet from MSDN should help you accomplish what you're doing:
string wordToFind = "melp";
int index = richTextBox1.Text.IndexOf( wordToFind );
while( index != -1 )
{
richTextBox1.Select( index, wordToFind.Length );
richTextBox1.SelectionColor = Color.Red;
index = richTextBox1.Text.IndexOf( wordToFind, index + wordToFind.Length );
}

Unity Input Field Lock previously typed characters after a time

I've been messing around with a word game in Unity C# and have come to a standstill regarding an anti-cheat mechanic I want to implement.
Once the first letter has been entered into the input field, I start running a 2 second timer. After the 2 seconds, in the player does not submit or type another letter, the input field should lock the previously typed letters in place on the input field and any letters typed after should be typed after it.
Here's the code I have so far:
currTime = 0;
hasInput = false;
lockedString = "";
void Update(){
if(hasInput){
currTime += Time.deltaTime * 1;
if(currTime >= 2){
//Stores current string value of input field
lockedString = inputField.text;
}
}
}
void OnInputValueChange(){
currTime = 0;
hasInput = true;
if(lockedString != ""){
inputField.text = lockedString + inputField.text;
}
}
Right now I'm running OnInputValueChange() whenever the input field's value is changed. I also manage to store the string that's been entered so far once the timer hits 2 seconds, but I do not know how to make it so that the input field "locks" the locked string into the front and allow changes to the letters typed behind it. The code inputField.text = lockedString + inputField.text; simply adds the lockedString variable to the input field every time the value gets changed.
The desired outcome is as such in pseudo-code:
//User types "bu"
//2 second timer starts
//During these 2 seconds, user can delete "bu" or continue typing
//User deletes "bu" and types "ah"
//Once the 2 second timer ends, whatever string is now in input is locked
//"ah" is now locked at the front of the input field
//After locking "ah", user cannot delete it anymore, but can continue typing
Any insight to how I might achieve something like this will be most helpful. Thanks for taking the time to help, I really appreciate it!
Currently, you are simply concatenating the string. You will want to check if the string starts with the same characters, and if not, completely overwrite the input:
void Update() {
if (hasInput && ((Time.time - inputTime) > 2f))
{
//Stores current string value of input field
lockedString = inputField.text;
hasInput = false;
}
}
void OnInputValueChange() {
inputTime = Time.time;
hasInput = true;
if ((lockedString.Length > 0) && (inputField.text.IndexOf(lockedString) != 0)) {
// Replace invalid string
inputField.text = lockedString;
// Update cursor position
inputField.MoveTextEnd(false);
}
}
Note: I have implemented an alternate method of measuring the time passed. Feel free to replace this with your own method.

Logic trouble with loop

I am creating a windows form that is a random number guessing game. I've made these before in C++ and never had an issue, however I have a big one here- I have no idea how to get the user back to input a number after the loop has began running. Here is my code:
private void btnGuess_Click(object sender, EventArgs e)
{
int guess = 0;
int count = 0;
int accumulator = 0; // accumulator
Random rand = new Random();
int number = rand.Next(1, 100);
txtAnswer.Focus();
while (guess != number)
{
guess = int.Parse(txtAnswer.Text);
if (guess < number)
{
MessageBox.Show("Too Low! Guess again!");
txtAnswer.Text = "";
txtAnswer.Focus();
count++;
accumulator++;
}
else if (guess > number)
{
MessageBox.Show("Too High! Try again!");
txtAnswer.Text = "";
txtAnswer.Focus();
count++;
accumulator++;
}
else
{
MessageBox.Show("Correct! you guessed the number in " + accumulator + " tries!");
break;
}
}
}
}
}
I just filled the while loop arguments with something for you guys, even though i know it won't work. Basically, I need to run the loop, get feedback (if the users guess was too high or low) then get the user to be able to input another number BEFORE the loop runs again. I don't know how to get that to happen with a text box control which is where the input will be. Any ideas?
You should not loop inside in the btnGuess_Click. Instead you need to store the state (the number, count, and the accumulator variables) in the scope of the form itself.
Initialize the random number when the form loads, or using some kind of start button.
Then inside the guess button handler, read the text box value and compare it to the number variable, such as what you are doing currently.
What you are building is more a console style application. So there is 1 main loop that is executing all the code.
In forms applications it is an event driven environment. So the user gets a form, presses a button, the form is evaluated and then the method handling ends.
So you have on a class level some variables for counts, in the constructor you add the initialization and the method for submit will be something like
private void btnGuess_Click(object sender, EventArgs e)
{
//Increment counters
//Check
//Show feedback
//Leave the button click code
}
For some more info, check this out:
https://msdn.microsoft.com/en-us/library/dd492132.aspx

C# textbox user input processed by a button object [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# GUI application that stores an array and displays the highest and lowest numbers by clicking a button
This is updated from 13 hours ago as I have been researching and experimenting with this for a few. I'm new to this programming arena so I'll be short, I'm teaching myself C# and I'm trying to learn how to have integers from a user's input into a textbox get calculated from a button1_Click to appear on the form. Yes, this is a class assignment but I think I have a good handle on some of this but not all of it; that's why I'm turning to you guys. Thanks for all of the advice guys.
I'm using Microsoft Visual Studio 2010 in C# language. I'm using Windows Forms Application and I need to create a GUI that allows a user to enter in 10 integer values that will be stored in an array called from a button_Click object. These values will display the highest and lowest values that the user inputted. The only thing is that the array must be declared above the Click() method.
This is what I have come up with so far:
namespace SmallAndLargeGUI
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void inputText_TextChanged(object sender, EventArgs e)
{
this.Text = inputText.Text;
}
public void submitButton_Click(object sender, EventArgs e)
{
int userValue;
if(int.TryParse(inputText.Text, out userValue))
{
}
else
{
MessageBox.Show("Please enter a valid integer into the text box.");
}
int x;
x = Convert.x.ToString();
int squaredResults = squared(x);
int cubedResults = cubed(x); squared(x);
squaredLabel.Text = x.ToString() + " squared is " + squaredResults.ToString();
cubedLabel.Text = x.ToString() + " cubed is " + cubedResults.ToString();
}
public static int squared(int x)
{
x = x * x;
return x;
}
public static int cubed(int x)
{
x = x * squared(x);
return x;
}
}
}
Now I can't run this program because line 38 shows an error message of: 'System.Convert' does not contain a definition for 'x' Also I still have to have an array that holds 10 integers from a textbox and is declared above the Click() method. Please guys, any help for me? This was due yesterday.
As a couple of comments have mentioned, there really isn't enough information here to provide you with a useful answer. There are two main User Interface frameworks in .Net for windows applications. One of these is commonly referred to as "WinForms" and the other is "WPF" or "Windows Presentation Foundation."
I'm going to go with you are most likely using WinForms as it is the older of the two technologies. The approach here can be used on both sides with a little tweaking. Setting text in a text box is very similar to setting text programaticly on a label. You can get more detail on that on MSDN: How to: Display Text on a Windows Form; How to: Use TextBox Controls to Get User Input.
If you are using WPF the "back end" code is pretty much the same. You just need to make sure your textbox has an x:Name="userInputTextBox" so you can reference it in your code behind. Be mindful that your users can input "1", "3" or "abcd" in the field. Ensuring your app doesn't bomb is most likely outside of the assignment but feel free to look up C# int.TryParse(...) and "Try Catch" :-)
Your button handler could look like this:
void btnUserClick_Click(object sender, System.EventArgs e)
{
int userValue;
if(int.TryParse(txtUserInput.Text, out userValue))
{
// We have the value successfully, do calculation
}
else
{
// We don't have the users value.
MessageBox.Show("Please enter a valid integer into the text box.")
}
}
In your retrieveInput_Click handler you are assigning the min/max numbers to a local int. Once you determine your min/max numbers in the logic, you will need to assign those local integers to a UI element for display.
Since we don't have any details on your specific UI choices, one simple solution could be to add 2 labels to your form, and then in the code you would place the result in the label:
for (int i = 0; i < numbers.Length; ++i)
{
if (numbers[i] < min)
min = numbers[i];
if (numbers[i] > max)
max = numbers[i];
}
// Assign Minimum to Label1
Label1.Text = "Minimum Value: " + min.ToString();
// Assign Maximum to Label2
Label2.Text = "Maximum Value: " + max.ToString();
define the textbox named textbox1 or txt_name
you can write the button1_Click function :
int i_value = Convert.ToInt16(txt_name.Text);
ok. I haven't try catch the exceptions.... :(
maybe above answer is right.
btw, i think this question mainly focus on how to get int type from text box. right?

Categories

Resources