I want to prevent one particular character * (asterisk) from being entered or pasted into a text box.
I tried:
key_press event - but it does not handle the case when user pastes an asterisk to the text box.
text_changed event - but when I remove the character, the cursor position goes back to the beginning of the text.
So I am wondering how to handle it, preferably in one event.
use the text changed event, but save the location of the cursor (the SelectionStart and SelectionEnd properties) before you remove the asterisk, then re set the cursor position (less the number of asterisks removed before the cursor).
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
var currentText = textBox1.Text;
var selectionStart = textBox1.SelectionStart;
var selectionLength = textBox1.SelectionLength;
int nextAsterisk;
while ((nextAsterisk = currentText.IndexOf('*')) != -1)
{
if (nextAsterisk < selectionStart)
{
selectionStart--;
}
else if (nextAsterisk < selectionStart + selectionLength)
{
selectionLength--;
}
currentText = currentText.Remove(nextAsterisk, 1);
}
if (textBox1.Text != currentText)
{
textBox1.Text = currentText;
textBox1.SelectionStart = selectionStart;
textBox1.SelectionLength = selectionLength;
}
}
This question may be of use to you. What you're looking for seems like either a MaskedTextBox or a TextBox with custom Validation logic. You should not simply erase an asterisk characters when it is input, because if a user has selected text, then typed an asterisk, they will have replaced the selected text with an asterisk before you have the chance to remove it.
You can set the cursor postion. For example:
textBox1.SelectionStart = textBox1.Text.Length;
EDIT:
Ok i took some time to write you a solution that works quite good. It keeps the edit cursor at the proper position and also covers the situation in which user pastes some * chars between chars.
int position = this.textBox1.SelectionStart;
string str = this.textBox1.Text;
int hit = 0;
for (int i = 0; i < position; i++)
{
if (str[i].Equals('*'))
hit++;
}
str = str.Replace("*", "");
this.textBox1.Text = str;
this.textBox1.SelectionLength = 0;
this.textBox1.SelectionStart = position - hit;
Here is the solution i found:-
On Text_changed event, here is what i am doing:-
txt1.Text = txt1.Text.Replace("*", string.Empty);
txt1.Select(txt1.Text.Length, 0);
Updated code:-
On Text_changed event:-
int curpos = 0;
bool isReplaced = false;
private void txt1_TextChanged(object sender, EventArgs e)
{
if (txt1.Text.Contains('*'))
{
curpos = txt1.SelectionStart;
isReplaced = true;
}
txt1.Text = txt1.Text.Replace("*", string.Empty);
if (isReplaced)
{
txt1.Select(curpos.Equals(0) ? 0 : curpos -1, 0);
isReplaced = false;
}
}
Final code and Tested :-
if (txt1.Text.Contains('*'))
{
foreach (char c in txt1.Text)
if (c.Equals('*'))
barredCharCount += 1;
curPosition = txt1.SelectionStart;
isTextReplaced = true;
}
txt1.Text = txt1.Text.Replace("*", string.Empty);
if (isTextReplaced)
{
txt1.Select(curPosition.Equals(0) ? 0 : curPosition - barredCharCount, 0);
isTextReplaced = false;
curPosition = barredCharCount = 0;
Console.Beep(); //does not work on 64 bit system
}
This piece of code is tested and working perfectly...
Related
I have a windows form application that use a RichTextBox to display a text from a file. There is also a TextBox and a Button to perform a search in the text. Whenever the button is clicked, the content of the TextBox is searched and enlightened in the RichTextBox. Here is the code in the button_Click event handler:
String search = richtextboxContent.Text;
richtextboxContent.Text = "";
richtextboxContent.Text = search;
#region code Search
string keyword = textboxsearch.Text.Trim();
int startPosition = 0;
int endPosition = 0;
int endArticle = richtextboxContent.Text.Length;
for (int i = 0; i < endArticle; i = startPosition)
{
if (i == -1)
{
break;
}
startPosition = richtextboxContent.Find(keyword, startPosition, endArticle, RichTextBoxFinds.None);
if (startPosition >= 0)
{
count++;
richtextboxContent.SelectionBackColor = Color.Yellow;
endPosition = textboxsearch.Text.Length;
startPosition = startPosition + endPosition;
}
}
I have one text file of 20mb with 90.000++ lines, whenever I search one word (that resulted with 1300 matchs) the code below take more than 10 minutes to finish.
How can it be improved ?
I have a WinForms application where a number of lines are drawn in a TeeChart component. It is requested that it shall be possible to delete a line by right-clicking it.
Everything works fine, the clickseries event is captured and so on, but the user finds it difficult to hit the line on right click. The question is, is it possible to increase the region where the Line/FastLine object is sensible for clicking? That is, make the line wider without drawing the line any wider on the screen.
Tnx in advance
Yes, this is possible. The key to achieve that is PointInLineTolerance method. To achieve what you request you can combine it with NearestPoint's tool GetNearestPoint method as shown in this example:
public Form1()
{
InitializeComponent();
InitializeChart();
}
private void InitializeChart()
{
tChart1.Aspect.View3D = false;
tChart1.Series.Add(new Steema.TeeChart.Styles.Line()).FillSampleValues();
tChart1.MouseMove += TChart1_MouseMove;
}
private void TChart1_MouseMove(object sender, MouseEventArgs e)
{
var nearestPoint = new Steema.TeeChart.Tools.NearestPoint(tChart1[0]);
nearestPoint.Active = false;
var p = new Point(e.X, e.Y);
var index = nearestPoint.GetNearestPoint(p);
if (index != -1)
{
const int tolerance = 10;
var px = tChart1[0].CalcXPos(index);
var py = tChart1[0].CalcYPos(index);
var index2 = (index == tChart1[0].Count - 1) ? index - 1 : index + 1;
var qx = tChart1[0].CalcXPos(index2);
var qy = tChart1[0].CalcYPos(index2);
if (Steema.TeeChart.Drawing.Graphics3D.PointInLineTolerance(p, px, py, qx, qy, tolerance))
{
tChart1.Header.Text = "point " + index.ToString() + " clicked";
}
else
{
tChart1.Header.Text = "No point";
}
}
An alternative could be using an invisible fake series with same data as the original series.
I want to change color of equal sign as it happens in notepad++ while the user writes the text . My code is working but the cursor is stuck on one place and user cannot write anything in between the text it only allows to write it in the end , also does not detect when newline is present after =. How to do it ?
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
equal();
}
public void equal()
{
start = richTextBox1.Text.Length - 1;
length = 1;
richTextBox1.SelectionStart = start;
richTextBox1.SelectionLength = length;
string settext = richTextBox1.SelectedText;
if ( settext ==Convert.ToString('='))
{
richTextBox1.SelectionColor = Color.Purple;
}
}
Add event to your richtext box for text changed:
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
this.ChangeColor("=", Color.Purple);
}
private void ChangeColor(string word, Color color)
{
if (this.richTextBox1.Text.Contains(word))
{
int index = -1;
int selectStart = this.richTextBox1.SelectionStart;
while ((index = this.richTextBox1.Text.IndexOf(word, (index + 1))) != -1)
{
this.richTextBox1.Select((index), word.Length);
this.richTextBox1.SelectionColor = color;
this.richTextBox1.Select(selectStart, 0);
this.richTextBox1.SelectionColor = Color.Black;
}
}
}
Please use the richTextBox_TextChanged event for changing the color. I have met this problem once in my application.
I'm trying to iterate through some pre-typed text in a Richtextbox and change the color of specific words/lines to a color depending on their prefix, thus far the different prefix's are [b], [f], and [e]. In this example I only use [b]. I've tried using while/foreach loops but they don't seem to iterate through the text. Below is the closest I've come to making it work but it only works on the first line of text. Any chance someone can point me in the correct direction?
private void AboutBox_Load(object sender, EventArgs e)
{
textBox1.Select(0, 0);
using (StringReader reader = new StringReader(richTextBox1.Text))
{
string line = string.Empty;
do
{
line = reader.ReadLine();
if ((line != null && line.Contains("[b]")))
{
richTextBox1.Select(richTextBox1.Text.IndexOf("[b]"), "[b]".Length);
richTextBox1.SelectionColor = Color.Green;
}
} while (line != null);
}
}
Instead of copying the text to a string, you can work directly with the RichTextBox via its Find() method:
void AboutBox_Load(object sender, EventArgs e)
{
this.ColorPrefix(richTextBox1, "[b]", Color.Green);
this.ColorPrefix(richTextBox1, "[f]", Color.Red); // change the color!
this.ColorPrefix(richTextBox1, "[e]", Color.Yellow); // change the color!
}
private void ColorPrefix(RichTextBox rtb, string prefix, Color color)
{
int position = 0, index = 0;
while ((index = rtb.Find(prefix, position, RichTextBoxFinds.None)) >= 0)
{
rtb.Select(index, prefix.Length);
rtb.SelectionColor = color;
position = index + 1;
}
rtb.Select(rtb.TextLength, 0);
}
This line will always select the same item:
richTextBox1.Select(richTextBox1.Text.IndexOf("[b]"), "[b]".Length);
So I would suggest something like this:
private void AboutBox_Load(object sender, EventArgs e)
{
string text = richTextBox1.Text;
int position = 0, index = 0;
while ((index = text.IndexOf("[b]", position)) >= 0)
{
richTextBox1.Select(index, 3);
richTextBox1.SelectionColor = Color.Green;
position = index + 1;
}
}
If you like to highlight syntax, I suggest using the FastColoredTextBox control:
hello atm I have this code
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked == true)
{
x = 0;
timer1.Enabled = true;
timer1.Start();
}
else
{
timer1.Enabled = false;
}
}
private int x = 0;
private int y = 0;
private void timer1_Tick(object sender, EventArgs e)
{
if (x <= 10)
{
x++;
string ping = new string(' ', x) + "hello";
label1.Text = ping;
if (x == 10)
{
y = 10;
}
}
else if (y > 0)
{
y--;
string pong = new string(' ', y) + "hello";
label1.Text = pong;
if (y == 0)
{
x = 0;
}
}
}
at the moment the label has a maximum length of 15 characters and i want it to stay that way.
but i want it to instead of using "hello" to take the text i input into a textbox and do it.
however it has to take 15 and subtract the length of the textboxes text in order to keep the labels max length of 15 intact while displaying the entire word in the textbox aswell but i cant figure out how to do it i have tried plenty of things but i cannot figure it out any help would be greatly appreciated. :D
Your use of the words "ping" and "pong", plus your title saying "move back and forth" leads me to believe the result you want can be achieved by changing the TextAlign property of the label upon each tick.
If this is the result you want, you won't have to add spaces at all. The text will appear to go from left to right edges in the label. You might consider trimming the text property with TRIM() to ensure no spaces exist on either side that would make it appear aligned incorrectly.