For TextBox, has a attribute "MaxLength",but it count all ascii and unicode as 1 character。
But in database, we set the field varchar(n) . It treats the ascii 1 and the unicode 2。
How can I limit the textbox input by the byte?
Because no notify before text changed, workaround like this.
public class TextBoxEx : TextBox
{
private bool bIsChanging;
public TextBoxEx()
{
TextChanged += TextBoxEx_TextChanged;
}
public int MaxByteLength { private get; set; }
private void TextBoxEx_TextChanged(object sender, TextChangedEventArgs e)
{
if (bIsChanging || MaxByteLength == 0 || Text.Length*2 <= MaxByteLength)
return;
bIsChanging = true;
int start = SelectionStart;
Text = TruncateString(Text, MaxByteLength);
SetLimit();
SelectionStart = start;
bIsChanging = false;
}
private void SetLimit()
{
MaxLength = MaxByteLength - Encoding.UTF8.GetBytes(Text).Length + Text.Length;
}
private static string TruncateString(string text, int max)
{
if (max == 0) return text;
byte[] bytes = Encoding.UTF8.GetBytes(text);
if (bytes.Length <= max) return text;
char[] c = text.ToCharArray();
var sb = new StringBuilder();
int count = 0;
foreach (char t in c)
{
count += Encoding.UTF8.GetByteCount(t.ToString());
if (max >= count)
{
sb.Append(t);
}
else
{
break;
}
}
return sb.ToString();
}
}
ascii code is hexadecimal as well, which means one character stands for 2 bytes of information
EX: "A" is 41(Hx) 0100 0001 which is 2 bytes and so on
I think you should refer this answer
It suggests to handle this your self (In this case, it limits 12 bytes length):
private void textBox1_TextChanged(object sender, EventArgs e)
{
var textBytes = Encoding.UTF8.GetBytes(textBox1.Text);
var textByteCount = Encoding.UTF8.GetByteCount(textBox1.Text);
var textCharCount = Encoding.UTF8.GetCharCount(textBytes);
if (textCharCount != textByteCount && textByteCount >= 12)
{
textBox1.Text = Encoding.UTF32.GetString(Encoding.UTF32.GetBytes(textBox1.Text), 0, 12);
}
else if (textBox1.Text.Length >= 6)
{
textBox1.Text = textBox1.Text.Substring(0, 6);
}
}
I'd simply use MaxLength of half the n in varchar(n).
Related
In my RichtextBox, if I have written as below.
This is my pen,
his pen is beautiful.
Now I search word "is" then
output would be as below.
All "is" should be highlighted.
What about:
static class Utility {
public static void HighlightText(this RichTextBox myRtb, string word, Color color) {
if (word == string.Empty)
return;
int s_start = myRtb.SelectionStart, startIndex = 0, index;
while((index = myRtb.Text.IndexOf(word, startIndex)) != -1) {
myRtb.Select(index, word.Length);
myRtb.SelectionColor = color;
startIndex = index + word.Length;
}
myRtb.SelectionStart = s_start;
myRtb.SelectionLength = 0;
myRtb.SelectionColor = Color.Black;
}
}
Looks like this would do it.
http://www.dotnetcurry.com/ShowArticle.aspx?ID=146
int start = 0;
int indexOfSearchText = 0;
private void btnFind_Click(object sender, EventArgs e)
{
int startindex = 0;
if(txtSearch.Text.Length > 0)
startindex = FindMyText(txtSearch.Text.Trim(), start, rtb.Text.Length);
// If string was found in the RichTextBox, highlight it
if (startindex >= 0)
{
// Set the highlight color as red
rtb.SelectionColor = Color.Red;
// Find the end index. End Index = number of characters in textbox
int endindex = txtSearch.Text.Length;
// Highlight the search string
rtb.Select(startindex, endindex);
// mark the start position after the position of
// last search string
start = startindex + endindex;
}
}
public int FindMyText(string txtToSearch, int searchStart, int searchEnd)
{
// Unselect the previously searched string
if (searchStart > 0 && searchEnd > 0 && indexOfSearchText >= 0)
{
rtb.Undo();
}
// Set the return value to -1 by default.
int retVal = -1;
// A valid starting index should be specified.
// if indexOfSearchText = -1, the end of search
if (searchStart >= 0 && indexOfSearchText >=0)
{
// A valid ending index
if (searchEnd > searchStart || searchEnd == -1)
{
// Find the position of search string in RichTextBox
indexOfSearchText = rtb.Find(txtToSearch, searchStart, searchEnd, RichTextBoxFinds.None);
// Determine whether the text was found in richTextBox1.
if (indexOfSearchText != -1)
{
// Return the index to the specified search text.
retVal = indexOfSearchText;
}
}
}
return retVal;
}
// Reset the richtextbox when user changes the search string
private void textBox1_TextChanged(object sender, EventArgs e)
{
start = 0;
indexOfSearchText = 0;
}
This will show all the searched criteria at the same time.
Using: 1 Textbox (to enter the text to search for) and 1 Button (to Run the Search).
Enter your search criteria inside the textbox and press search button.
// On Search Button Click: RichTextBox ("rtb") will display all the words inside the document
private void btn_Search_Click(object sender, EventArgs e)
{
try
{
if (rtb.Text != string.Empty)
{// if the ritchtextbox is not empty; highlight the search criteria
int index = 0;
String temp = rtb.Text;
rtb.Text = "";
rtb.Text = temp;
while (index < rtb.Text.LastIndexOf(txt_Search.Text))
{
rtb.Find(txt_Search.Text, index, rtb.TextLength, RichTextBoxFinds.None);
rtb.SelectionBackColor = Color.Yellow;
index = rtb.Text.IndexOf(txt_Search.Text, index) + 1;
rtb.Select();
}
}
}
catch (Exception ex) { MessageBox.Show(ex.Message, "Error"); }
}
}
}
If you only want to match the whole word you can use this, note that this ignores case and also the |s\b means that plurals get highlighted e.g. Cat matches cats but not caterpiller :
public static void HighlightText(RichTextBox myRtb, string word, Color color)
{
if (word == string.Empty)
return;
var reg = new Regex(#"\b" + word + #"(\b|s\b)",RegexOptions.IgnoreCase);
foreach (Match match in reg.Matches(myRtb.Text))
{
myRtb.Select(match.Index, match.Length);
myRtb.SelectionColor = color;
}
myRtb.SelectionLength = 0;
myRtb.SelectionColor = Color.Black;
}
private void button3_Click(object sender, EventArgs e)
{
if (textBox1.Text != "")
{
for (int i = 0; i < richTextBox1.TextLength; i++)
{
richTextBox1.Find(textBox1.Text, i, RichTextBoxFinds.None);
richTextBox1.SelectionBackColor = Color.Red;
}
}
else
{
for (int i = 0; i < richTextBox1.TextLength; i++)
{
richTextBox1.SelectAll();
richTextBox1.SelectionBackColor = Color.White;
}
}
}[lets make it!][1]
I would do it like that because all the other answers highlight the text, but doesnt change it back after you searched again.
Use the RichText Find Method to find the starting index for the searching word.
public int FindMyText(string searchText, int searchStart, int searchEnd)
{
int returnValue = -1;
if (searchText.Length > 0 && searchStart >= 0)
{
if (searchEnd > searchStart || searchEnd == -1)
{
int indexToText = richTextBox1.Find(searchText, searchStart, searchEnd, RichTextBoxFinds.MatchCase);
if (indexToText >= 0)
{
returnValue = indexToText;
}
}
}
return returnValue;
}
Use a Button or TextChangeListener and Search for your word.
private void button1_Click(object sender, EventArgs e)
{
// Select the first char in your Richtextbox
richTextBox1.SelectionStart = 0;
richTextBox1.SelectionLength = richTextBox1.TextLength;
// Select until the end
richTextBox1.SelectionColor = Color.Black;
// Make the Text Color black
//Use an Inputfield to add the searching word
var word = txtSearch.Text;
//verify the minimum length otherwise it may freeze if you dont have text inside
if (word.Length > 3)
{
int s_start = richTextBox1.SelectionStart, startIndex = 0, index;
while ((index = FindMyText(word, startIndex, richTextBox1.TextLength)) != -1)
{
// goes through all possible found words and color them blue (starting index to end)
richTextBox1.Select(index, word.Length);
richTextBox1.SelectionColor = Color.Blue;
startIndex = index + word.Length;
}
// Color everything between in color black to highlight only found words
richTextBox1.SelectionStart = startIndex;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionColor = Color.Black;
}
}
I would highly recommend to set a minimum word length to avoid freezing and high memory allocation.
I have a program where i need to count how many females and Males are in the file that has been read into the richtextbox, but I'm not sure how to do that , in the file has the name, gender,specific job . I have to count between 15 different people
for example : " Donna,Female,Human Resources.",
This is what I have so far:
private void Form1_Load(object sender, EventArgs e)
{
StreamReader sr;
richTextBox1.Clear();
sr = new StreamReader("MOCK_DATA.txt");
string data;
while (!sr.EndOfStream)
{
data = sr.ReadLine();
richTextBox1.AppendText(data + "\n");
}
}
private void button1_Click(object sender, EventArgs e)
{
string[] data = richTextBox1.Text.Split(',');
for (int n = 0; n < data.Length; n++)
{
if (data[n] == richTextBox1.Text)
n++;
To get the plain text from a RichTextBox (stolen from this article):
string StringFromRichTextBox(RichTextBox rtb)
{
TextRange textRange = new TextRange(
// TextPointer to the start of content in the RichTextBox.
rtb.Document.ContentStart,
// TextPointer to the end of content in the RichTextBox.
rtb.Document.ContentEnd
);
// The Text property on a TextRange object returns a string
// representing the plain text content of the TextRange.
return textRange.Text;
}
Basic word counting routine:
int CountWord(string textToSearch, string word)
{
int count = 0;
int i = textToSearch.IndexOf(word);
while (i != -1)
{
count++;
i = textToSearch.IndexOf(word, i+1);
}
return count;
}
Putting it together:
var plainText = StringFromRichTextBox(richTextBox1);
var countOfMale = CountWord(plainText, "Male");
var countOfFemale = CountWord(plainText, "Female");
private void toolStripButton81_Click(object sender, EventArgs e)
{
string findterm = string.Empty;
findterm = toolStripTextBox2.Text;
// the search term - specific word
int loopCount = 0;
// count the number of instance
int findPos = 0;
// depending on checkbox settings
// whole word search or match case etc
try
{
while (findPos < GetRichTextBox().Text.Length)
{
if (wholeWordToolStripMenuItem.CheckState == CheckState.Checked & matchCaseToolStripMenuItem.CheckState == CheckState.Checked)
{
findPos = GetRichTextBox().Find(findterm, findPos, RichTextBoxFinds.WholeWord | RichTextBoxFinds.MatchCase);
}
else if (wholeWordToolStripMenuItem.CheckState == CheckState.Checked)
{
findPos = GetRichTextBox().Find(findterm, findPos, RichTextBoxFinds.WholeWord);
}
else if (matchCaseToolStripMenuItem.CheckState == CheckState.Checked)
{
findPos = GetRichTextBox().Find(findterm, findPos, RichTextBoxFinds.MatchCase);
}
else
{
findPos = GetRichTextBox().Find(findterm, findPos, RichTextBoxFinds.None);
}
GetRichTextBox().Select(findPos, toolStripTextBox2.Text.Length);
findPos += toolStripTextBox2.Text.Length + 1;
loopCount = loopCount + 1;
}
}
catch
{
findPos = 0;
}
// at the end bring the cursor at the beginning of the document
GetRichTextBox().SelectionStart = 0;
GetRichTextBox().SelectionLength = 0;
GetRichTextBox().ScrollToCaret();
// Show the output in statusbar
toolStripStatusLabel2.Text = "Instances: " + loopCount.ToString();
}
I'm trying to create a method to pass a string to the method, and then I want to display the number of words in the string. The string being the user input from the textbox.
private void button1_Click(object sender, EventArgs e)
{
countMethod();
}
private string countMethod()
{
String text = textBox1.Text.Trim();
int wordCount = 0, index = 0;
while (index < text.Length)
{
// check if current char is part of a word
while (index < text.Length && Char.IsWhiteSpace(text[index]) == false)
index++;
wordCount++;
// skip whitespace until next word
while (index < text.Length && Char.IsWhiteSpace(text[index]) == true)
index++;
}
return MessageBox.Show(wordCount.ToString());
}
EDIT:
I added an argument to the method. And send the wordCount to a string, once the loop was done. I tried it several times and it works. I'm new to programming, and is there a reason why this wouldn't work or should do it another way? Thanks
private void button1_Click(object sender, EventArgs e)
{
string userInput = textBox1.Text;
countMethod(userInput);
}
private string countMethod(string input)
{
string text = textBox1.Text.Trim();
int wordCount = 0, index = 0;
while (index < text.Length)
{
// check if current char is part of a word
while (index < text.Length && Char.IsWhiteSpace(text[index]) == false)
index++;
wordCount++;
// skip whitespace until next word
while (index < text.Length && Char.IsWhiteSpace(text[index]) == true)
index++;
}
string total = wordCount.ToString();
MessageBox.Show("The total words in this string are: " +total);
return total;
}
There is an easier way to do it!
private void button1_Click(object sender, EventArgs e)
{
var wordCount = CountWords(textBox1.Text);
MessageBox.Show(wordCount.ToString());
}
private int CountWords(string input)
{
var separators = new[] { ' ', '.' };
var count = input.Split(separators, StringSplitOptions.RemoveEmptyEntries).Length;
return count;
}
Add/Remove the separators you want to/from the separators array.
Try to use extension method. It's good idea.
public static class MyExtentionClass
{
public static int WordCount(this string str)
{
var separators = new[] { ' ', '.', ',' };
var count = str.Split(separators, StringSplitOptions.RemoveEmptyEntries).Length;
return count;
}
}
eg:
MessageBox.Show(textBox1.Text.WordCount());
Split on white spaces then get the count
int wordCount = textBox1.Text.Trim().Split(" ").Count;
I want to add "," to after every group of 3 digits. Eg : when I type 3000000 the textbox will display 3,000,000 but the value still is 3000000.
I tried to use maskedtexbox, there is a drawback that the maskedtexbox displayed a number like _,__,__ .
Try adding this code to KeyUp event handler of your TextBox
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (!string.IsNullOrEmpty(textBox1.Text))
{
System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");
int valueBefore = Int32.Parse(textBox1.Text, System.Globalization.NumberStyles.AllowThousands);
textBox1.Text = String.Format(culture, "{0:N0}", valueBefore);
textBox1.Select(textBox1.Text.Length, 0);
}
}
Yes, it will change the value stored in a texbox, but whenever you need the actual number you can use the following line to get it from the text:
int integerValue = Int32.Parse(textBox1.Text, System.Globalization.NumberStyles.AllowThousands);
Of course do not forget to check that what the user inputs into the textbox is actually a valid integer number.
Use String.Format
int value = 300000
String.Format("{0:#,###0}", value);
// will return 300,000
http://msdn.microsoft.com/en-us/library/system.string.format.aspx
This may work fine for your scenario I hope.
private string text
{
get
{
return text;
}
set
{
try
{
string temp = string.Empty;
for (int i = 0; i < value.Length; i++)
{
int p = (int)value[i];
if (p >= 48 && p <= 57)
{
temp += value[i];
}
}
value = temp;
myTxt.Text = value;
}
catch
{
}
}
}
private void digitTextBox1_TextChanged(object sender, EventArgs e)
{
if (myTxt.Text == "")
return;
int n = myTxt.SelectionStart;
decimal text = Convert.ToDecimal(myTxt.Text);
myTxt.Text = String.Format("{0:#,###0}", text);
myTxt.SelectionStart = n + 1;
}
Here, myTxt = your Textbox. Set Textchanged event as given below and create a property text as in the post.
Hope it helps.
You could hook up to OnKeyUp event like this:
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (!(e.KeyCode == Keys.Back))
{
string text = textBox1.Text.Replace(",", "");
if (text.Length % 3 == 0)
{
textBox1.Text += ",";
textBox1.SelectionStart = textBox1.Text.Length;
}
}
}
Get Decimal Value Then set
DecimalValue.ToString("#,#");
I have two words:
Source: John
ConvertTo: Jack
and I want to show the effect of convert all letters from "Source" at the same time to the "ConvertTo" word. I already create a program to accomplish that but processing one letter at a time, to show the effect I use Threads, the thing is that to process all letters at the same time I suppose I need one thread per letter, and every thread will call the same function that process the letter, and I use global variables.
Here is the code (works only for texts with same lenght):
private void button1_Click(object sender, EventArgs e)
{
lblResult.Text = "";
lblResult2.Text = "";
ThreadPool.QueueUserWorkItem(new WaitCallback(Process));
}
int movement = 0;
string CumulateText;
private void Process(object stateinfo)
{
int value;
int operation; //0->[+] 1->[-]
CumulateText = "";
for (int i = 0; i <= textBox1.Text.Length - 1; i++)
{
if (textBox1.Text[i] != ' ')
{
value = (char)textBox1.Text[i] - (char)textBox2.Text[i];
if (value >= 0)
operation = 1;
else
operation = 0;
for (int ii = 0; ii <= Math.Abs(value); ii++)
{
if (operation == 1)
movement = (char)textBox1.Text[i] - ii;
else
movement = (char)textBox1.Text[i] + ii;
this.Invoke(new EventHandler(ShowMovement));
System.Threading.Thread.Sleep(10);
}
}
CumulateText += textBox2.Text[i].ToString();
}
}
private void ShowMovement(object sender, EventArgs e)
{
lblResult.Text = CumulateText + Convert.ToString((char)movement);
}
I hope I made myself understood.
please any advise to accomplish that.
thanks
To clarify more what I want to accomplish here is an example:
Source: John
ConvertTo: Jack
J - same J
o - decrease till a (o, n, m, ..., a)
h - decrease till c (h, g, f, ..., c)
n - decrease till k (n, m, l, k)
I once had to do something similar for a small little project I was working on for fun.
I do not see why you would need to create a thread for each letter to create a transition between two words unless I'm not understanding what you are pretending to do correctly.
Check and study the following code, see if its any help:
static class Program
{
static void Main()
{
TextTranstition transition = new TextTranstition();
transition.TransitionFinished += TransitionTicked;
transition.TransitionTicked += TransitionTicked;
transition.StartTransition("AmazingWordTransition", "MyNewWordAppearing", 100);
Thread.CurrentThread.Join();
Console.ReadKey();
}
public static void TransitionTicked(object sender, TranstitionEventArgs e)
{
Console.Clear();
Console.Write(e.TransitionText);
}
}
public class TranstitionEventArgs : EventArgs
{
private readonly string transitionText;
public string TransitionText { get { return this.transitionText; } }
public TranstitionEventArgs(string transitionText)
{
this.transitionText = transitionText;
}
}
public class TextTranstition
{
private struct StartInfo
{
public StartInfo(string initialText, string finalText, int timeStep)
{
this.initialText = initialText;
this.finalText = finalText;
this.timeStep = timeStep;
}
private readonly string initialText;
public string InitialText { get { return this.initialText; } }
private readonly string finalText;
public string FinalText { get { return this.finalText; } }
private readonly int timeStep;
public int TimeStep { get { return this.timeStep; } }
}
public EventHandler<TranstitionEventArgs> TransitionFinished;
public EventHandler<TranstitionEventArgs> TransitionTicked;
public void StartTransition(string initialText, string finalText, int timeStep)
{
StartInfo startInfo = new StartInfo(initialText, finalText, timeStep);
Thread t = new Thread(startTransition);
t.Start(startInfo);
}
private void startTransition(object info)
{
StartInfo startInfo = (StartInfo)info;
string initialText = startInfo.InitialText;
string finalText = startInfo.FinalText;
if (initialText.Length < finalText.Length)
{
initialText = initialText.PadRight(finalText.Length);
}
if (TransitionTicked != null) TransitionTicked(this, new TranstitionEventArgs(initialText));
while ((initialText = transition(initialText, finalText)) != finalText)
{
Thread.Sleep(startInfo.TimeStep);
if (TransitionTicked != null) TransitionTicked(this, new TranstitionEventArgs(initialText));
}
if (TransitionFinished != null) TransitionFinished(this, new TranstitionEventArgs(finalText));
}
private string transition(string initialText, string finalText)
{
StringBuilder b = new StringBuilder(finalText.Length);
for (int i = 0; i < finalText.Length; i++)
{
char c = initialText[i];
int charCode = (int)c;
if (c != finalText[i])
{
if (charCode == 122 || charCode==32) charCode = 65;
else if (charCode == 90) charCode = 97;
else
{
charCode += 1;
}
}
b.Append((char)charCode);
}
return b.ToString();
}
}
Use BackgroudWorker for this kind of stuff.