How to call a method from another one? - c#

I'm working on a code-editor and I want to call the string line into a keyargs event which is inside another void-returning method.
Output should occur when I type enter key, and then the selected-list from ComboBox should append to text held in RichTextBox.
Now to fulfill that, I'd like to ask you, how to call this method:
void Parse()
{
String inputLanguage =
"using System;\n" + "\n" +
"public class Stuff : Form { \n" +
" public static void Main(String args) {\n" +
"\n" + "\n" +
" }\n" +
"}\n";
// Foreach line in input,
// identify key words and format them when adding to the rich text box.
Regex r = new Regex("\\n");
String[] lines = r.Split(inputLanguage);
foreach (string l in lines)
{
ParseLine(l);
}
}
void ParseLine(string line)
{
Regex r = new Regex("([ \\t{}();])");
String[] tokens = r.Split(line);
foreach (string token in tokens)
{
// Set the token's default color and font.
rtb.SelectionColor = Color.Black;
rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);
// Check for a comment.
if (token == "//" || token.StartsWith("//"))
{
// Find the start of the comment and then extract the whole comment.
int index = line.IndexOf("//");
rtb.SelectedText = comment;
break;
}
// Check whether the token is a keyword.
var keywordsDef = new KeyWord();
String[] keywords = keywordsDef.keywords;
for (int i = 0; i < keywords.Length; i++)
{
if (keywords[i] == token)
{
// Apply alternative color and font to highlight keyword.
HighlighType.keywordsType(rtb);
break;
}
}
rtb.SelectedText = token;
}
rtb.SelectedText = "\n";
}
from within this one:
void lb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
lb.Visible = false;
lb.Items.Clear();
}
if (e.KeyCode == Keys.Enter)
{
//ParseLine(string line);
Parse();
string comment = line.Substring(index, line.Length - index);
rtb.SelectedText = comment + " " + lb.SelectedIndex.ToString();
}
}
I really need help. Big thanks in advance!

You are passing the parameter wrong. You can not pass a type when calling a method. The commented line should read
ParseLine(line);
The variable line must be declared somewhere above ParseLine. What it contains is up to you, but probably you want to set
string line = lb.Text;
So your code could read like this:
void lb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
lb.Visible = false;
lb.Items.Clear();
}
if (e.KeyCode == Keys.Enter)
{
string line = lb.Text;
ParseLine(line);
//Parse();
string comment = line.Substring(index, line.Length - index);
rtb.SelectionColor = Color.Green;
rtb.SelectionFont = new Font("Courier New", 10, FontStyle.Italic);
rtb.SelectedText = comment + " " + lb.SelectedIndex.ToString();
}
}

Calling the function is not the problem, but you need some way of retrieving the current line in whichever editor you're using. Once you have retrieved it, you can call ParseLine on it, but until you have it you have nothing to work on.

Related

WebForms RichTextBox Editing Approch?

I am using C# WinForm, and I have a RichTextBox that I am trying to make look like a C# script.
Means when using specific words, I want them to be colored. When they edit the word by changing it, I want it to go back to be black.
My approach works, but it really messy and cause bugs when the a scroll option is created and needed to be used to see the code below. (When typing, pretty much the richtextbox jumps up and down without stop)
private void ScriptRichTextBox_TextChanged(object sender, EventArgs e)
{
ScriptTextChange = ScriptRichTextBox.Text;
ScriptColorChange();
}
private void ScriptColorChange()
{
int index = ScriptRichTextBox.SelectionStart;
ScriptRichTextBox.Text = ScriptTextChange; //Only way I found to make the all current text black again, SelectAll() didn't work well.
ScriptRichTextBox.SelectionStart = index;
String[] coloredNames = {"Main", "ClickMouseDown", "ClickMouseUp", "PressKey", "StopMoving", "Delay", "GoRight", "GoLeft", "GoUp", "GoDown", "MousePosition", "LastHorizontalDirection", "LastVerticalDirections", "CurrentDirection", "Directions" };
String[] coloredNames2 = { "cm.", "if", "else", "while", "switch", "case", "break", "return", "new" };
String[] coloredNames3 = { "MyPosition", "MyHp", "MyMp", "OtherPeopleInMap", ".RIGHT", ".LEFT", ".UP", ".DOWN", ".STOP_MOVING" };
foreach (String s in coloredNames)
this.CheckKeyword(s, Color.LightSkyBlue, 0);
foreach (String s in coloredNames2)
this.CheckKeyword(s, Color.Blue, 0);
foreach (String s in coloredNames3)
this.CheckKeyword(s, Color.DarkGreen, 0);
}
private void CheckKeyword(string word, Color color, int startIndex)
{
if (this.ScriptRichTextBox.Text.Contains(word))
{
int index = 0;
int selectStart = this.ScriptRichTextBox.SelectionStart;
while ((index = this.ScriptRichTextBox.Text.IndexOf(word, (index + 1))) != -1)
{
this.ScriptRichTextBox.Select((index + startIndex), word.Length);
this.ScriptRichTextBox.SelectionColor = color;
this.ScriptRichTextBox.Select(selectStart, 0);
this.ScriptRichTextBox.SelectionColor = Color.Black;
}
}
}
I refactored your code a little to hopefully demonstrate a better approach to colouring the text. It is also not optimal to instantiate your string arrays every time you fire the TextChanged event.
Updated:The idea is to build up a word buffer that will be matched with your set of words when typing.
The buffer records each key and if it .IsLetterOrDigit it adds it to the StringBuilder buffer. The buffer has some additional bugs, with recording key press values and not removing recorded chars if you hit backspace etc..
Instead of the word buffer, use RegEx to match any of the words in your reserve word list. Build up the reserve word RegEx so you end up with something like \b(word|word2|word3....)\b This is done in the code in the BuildRegExPattern(..) method.
Once you hit any key other than a letter or number the buffer is checked for content and if the content matches a word then only the text right before the cursor in the ScriptRichTextBox.Text is checked and changed.
Remove the .(dots) from the reserve words as this just complicates the matching criteria. The RegEx in the built up patters will match the words exactly, so if you type something like FARRIGHT or cms the words will not partially change colour.
As an extra I also covered the paste process pressing Ctrl+V because it is a bit of a pain in WinForms and will probably happen quite often.
There are older questions eg. this one that cover the scrolling behaviour, where it shows how to interop by adding the [System.Runtime.InteropServices.DllImport("user32.dll")] attribute, but it can be done without it.
To prevent all the scroll jumping you can make use of the .DefWndProc(msg) method on the form. this question pointed me towards the WM_SETREDRAW property.
There is also this list of other properties that can be set.
The full implementation is this:
public partial class Form1 : Form
{
private readonly string[] _skyBlueStrings;
private readonly string[] _blueStrings;
private readonly string[] _greenStrings;
//for pasting
bool _IsCtrl;
bool _IsV;
//value to fix the colour not setting first character after return key pressed
int _returnIdxFix = 0;
//regex patterns to use
string _LightBlueRegX = "";
string _BlueRegX = "";
string _GreenRegX = "";
//match only words
Regex _rgxAnyWords = new Regex(#"(\w+)");
//colour setup
Color _LightBlueColour = Color.LightSkyBlue;
Color _BlueColour = Color.Blue;
Color _GreenColour = Color.DarkGreen;
Color _DefaultColour = Color.Black;
public Form1()
{
InitializeComponent();
_skyBlueStrings = new string[] { "Main", "ClickMouseDown", "ClickMouseUp", "PressKey", "StopMoving", "Delay", "GoRight", "GoLeft", "GoUp", "GoDown", "MousePosition", "LastHorizontalDirection", "LastVerticalDirections", "CurrentDirection", "Directions" };
_blueStrings = new string[] { "cm", "if", "else", "while", "switch", "case", "break", "return", "new" };
_greenStrings = new string[] { "MyPosition", "MyHp", "MyMp", "OtherPeopleInMap", "RIGHT", "LEFT", "UP", "DOWN", "STOP_MOVING" };
_LightBlueRegX = BuildRegExPattern(_skyBlueStrings);
_BlueRegX = BuildRegExPattern(_blueStrings);
_GreenRegX = BuildRegExPattern(_greenStrings);
}
string BuildRegExPattern(string[] keyworkArray)
{
StringBuilder _regExPatern = new StringBuilder();
_regExPatern.Append(#"\b(");//beginning of word
_regExPatern.Append(string.Join("|", keyworkArray));//all reserve words
_regExPatern.Append(#")\b");//end of word
return _regExPatern.ToString();
}
private void ProcessAllText()
{
BeginRtbUpdate();
FormatKeywords(_LightBlueRegX, _LightBlueColour);
FormatKeywords(_BlueRegX, _BlueColour);
FormatKeywords(_GreenRegX, _GreenColour);
//internal function to process words and set their colours
void FormatKeywords(string regExPattern, Color wordColour)
{
var matchStrings = Regex.Matches(ScriptRichTextBox.Text, regExPattern);
foreach (Match match in matchStrings)
{
FormatKeyword(keyword: match.Value, wordIndex: match.Index, wordColour: wordColour);
}
}
EndRtbUpdate();
ScriptRichTextBox.Select(ScriptRichTextBox.Text.Length, 0);
ScriptRichTextBox.Invalidate();
}
void ProcessWordAtIndex(string fullText, int cursorIdx)
{
MatchCollection anyWordMatches = _rgxAnyWords.Matches(fullText);
if (anyWordMatches.Count == 0)
{ return; } // no words found
var allWords = anyWordMatches.OfType<Match>().ToList();
//get the word just before cursor
var wordAtCursor = allWords.FirstOrDefault(w => (cursorIdx - _returnIdxFix) == (w.Index + w.Length));
if (wordAtCursor is null || string.IsNullOrWhiteSpace(wordAtCursor.Value))
{ return; }//no word at cursor or the match was blank
Color wordColour = CalculateWordColour(wordAtCursor.Value);
FormatKeyword(wordAtCursor.Value, wordAtCursor.Index, wordColour);
}
private Color CalculateWordColour(string word)
{
if (_skyBlueStrings.Contains(word))
{ return _LightBlueColour; }
if (_blueStrings.Contains(word))
{ return _BlueColour; }
if (_greenStrings.Contains(word))
{ return _GreenColour; }
return _DefaultColour;
}
private void FormatKeyword(string keyword, int wordIndex, Color wordColour)
{
ScriptRichTextBox.Select((wordIndex - _returnIdxFix), keyword.Length);
ScriptRichTextBox.SelectionColor = wordColour;
ScriptRichTextBox.Select(wordIndex + keyword.Length, 0);
ScriptRichTextBox.SelectionColor = _DefaultColour;
}
#region RichTextBox BeginUpdate and EndUpdate Methods
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
//wait until the rtb is visible, otherwise you get some weird behaviour.
if (ScriptRichTextBox.Visible && ScriptRichTextBox.IsHandleCreated)
{
if (m.LParam == ScriptRichTextBox.Handle)
{
rtBox_lParam = m.LParam;
rtBox_wParam = m.WParam;
}
}
}
IntPtr rtBox_wParam = IntPtr.Zero;
IntPtr rtBox_lParam = IntPtr.Zero;
const int WM_SETREDRAW = 0x0b;
const int EM_HIDESELECTION = 0x43f;
void BeginRtbUpdate()
{
Message msg_WM_SETREDRAW = Message.Create(ScriptRichTextBox.Handle, WM_SETREDRAW, (IntPtr)0, rtBox_lParam);
this.DefWndProc(ref msg_WM_SETREDRAW);
}
public void EndRtbUpdate()
{
Message msg_WM_SETREDRAW = Message.Create(ScriptRichTextBox.Handle, WM_SETREDRAW, rtBox_wParam, rtBox_lParam);
this.DefWndProc(ref msg_WM_SETREDRAW);
//redraw the RichTextBox
ScriptRichTextBox.Invalidate();
}
#endregion
private void ScriptRichTextBox_TextChanged(object sender, EventArgs e)
{
//only run all text if it was pasted NOT ON EVERY TEXT CHANGE!
if (_IsCtrl && _IsV)
{
_IsCtrl = false;
ProcessAllText();
}
}
protected void ScriptRichTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsLetterOrDigit(e.KeyChar))
{
//if the key was enter the cursor position is 1 position off
_returnIdxFix = (e.KeyChar == '\r') ? 1 : 0;
ProcessWordAtIndex(ScriptRichTextBox.Text, ScriptRichTextBox.SelectionStart);
}
}
private void ScriptRichTextBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.ControlKey)
{
_IsCtrl = true;
}
if (e.KeyCode == Keys.V)
{
_IsV = true;
}
}
private void ScriptRichTextBox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.ControlKey)
{
_IsCtrl = false;
}
if (e.KeyCode == Keys.V)
{
_IsV = false;
}
}
}
It looks like this when you paste some "code" with keywords:
and typing looks like this:
Ok after 2 days of not finding something that actually works good or has annoying bugs. I managed to find a solution myself after a big struggle of trying to make it work. The big idea is people try to edit all the RichTextBox words at once, which cause bugs. Why to edit all of the rich text box when you can do your checks on the current word only to get the same result. Which is what I did, I checked if any of my array strings is in the current word, and colored all of them.
private void ScriptRichTextBox_TextChanged(object sender, EventArgs e)
{
FindStringsInCurrentWord();
}
private void FindStringsInCurrentWord()
{
RichTextBox script = ScriptRichTextBox;
String finalWord, forwards, backwards;
int saveLastSelectionStart = script.SelectionStart;
int index = script.SelectionStart;
String[] coloredNames = { "Main", "ClickMouseDown", "ClickMouseUp", "PressKey", "StopMoving", "Delay", "GoRight", "GoLeft", "GoUp", "GoDown", "MousePosition", "LastHorizontalDirection", "LastVerticalDirections", "CurrentDirection", "Directions" };
String[] coloredNames2 = { "cm.", "if", "else", "while", "switch", "case", "break", "return", "new" };
String[] coloredNames3 = { "MyPosition", "MyHp", "MyMp", "OtherPeopleInMap", ".RIGHT", ".LEFT", ".UP", ".DOWN", ".STOP_MOVING" };
String[] arr2 = coloredNames.Union(coloredNames2).ToArray();
Array arrAll = arr2.Union(coloredNames3).ToArray(); //Gets all arrays together
Array[] wordsArray = { coloredNames, coloredNames2, coloredNames3 }; //All found strings in the word
List<String> wordsFoundList = new List<String>();
int foundChangedColor = 0;
int wordsFound = 0;
char current = (char)script.GetCharFromPosition(script.GetPositionFromCharIndex(index)); //Where the editor thingy is
//Check forward text where he uses space and save text
while (!System.Char.IsWhiteSpace(current) && index < script.Text.Length)
{
index++;
current = (char)script.GetCharFromPosition(script.GetPositionFromCharIndex(index));
}
int lengthForward = index - saveLastSelectionStart;
script.Select(script.SelectionStart, lengthForward);
forwards = script.SelectedText;
//Debug.WriteLine("Forwards: " + forwards);
script.SelectionStart = saveLastSelectionStart;
this.ScriptRichTextBox.Select(script.SelectionStart, 0);
index = script.SelectionStart;
current = (char)script.GetCharFromPosition(script.GetPositionFromCharIndex(index));
int length = 0;
//Check backwords where he uses space and save text
while ((!System.Char.IsWhiteSpace(current) || length == 0) && index > 0 && index <= script.Text.Length)
{
index--;
length++;
current = (char)script.GetCharFromPosition(script.GetPositionFromCharIndex(index));
}
script.SelectionStart -= length;
script.Select(script.SelectionStart + 1, length - 1);
backwards = script.SelectedText;
//Debug.WriteLine("Backwards: " + backwards);
script.SelectionStart = saveLastSelectionStart;
this.ScriptRichTextBox.Select(saveLastSelectionStart, 0);
this.ScriptRichTextBox.SelectionColor = Color.Black;
finalWord = backwards + forwards; //Our all word!
//Debug.WriteLine("WORD:" + finalWord);
//Setting all of the word black, after it coloring the right places
script.Select(index + 1, length + lengthForward);
script.SelectionColor = Color.Black;
foreach (string word in arrAll)
{
if (finalWord.IndexOf(word) != -1)
{
wordsFound++;
wordsFoundList.Add(word);
script.Select(index + 1 + finalWord.IndexOf(word), word.Length);
if (coloredNames.Any(word.Contains))
{
script.SelectionColor = Color.LightSkyBlue;
foundChangedColor++;
}
else if (coloredNames2.Any(word.Contains))
{
script.SelectionColor = Color.Blue;
foundChangedColor++;
}
else if (coloredNames3.Any(word.Contains))
{
script.SelectionColor = Color.DarkGreen;
foundChangedColor++;
}
//Debug.WriteLine("Word to edit: " + script.SelectedText);
this.ScriptRichTextBox.Select(saveLastSelectionStart, 0);
this.ScriptRichTextBox.SelectionColor = Color.Black;
}
}
//No strings found, color it black
if (wordsFound == 0)
{
script.Select(index + 1, length + lengthForward);
script.SelectionColor = Color.Black;
//Debug.WriteLine("WORD??: " + script.SelectedText);
this.ScriptRichTextBox.Select(saveLastSelectionStart, 0);
this.ScriptRichTextBox.SelectionColor = Color.Black;
}
}

I want make a text box area that automatically cuts a long paragraph

text box area that automatically cuts a long paragraph text into 30 characters sentences
i am trying run this code but occurs exception [exception of type 'System.StackOverflowException']
private void txtCutParagraph_TextChanged(object sender, EventArgs e)
{
int limitNum = 30;
string sentence = txtCutParagraph.Text;
string[] words = sentence.Split(' ');
string line = "";
foreach (string word in words)
{
if ((line + word).Length > limitNum)
{
newLine += line + "\r\n";
line = "";
}
line += word + " ";
}
if (line.Length > 0)
newLine += line + "\r\n";
txtCutParagraph.Text = newLine;
}
If the form is freezing is because that txtCutParagraph_TextChanged event is firing infinitely, because you are changing the text of textbox at the end of the event: txtCutParagraph.Text = newLine;, so it means that change text in the textbox, and the event will fire again and again.
To prevent this form from freezing please move your code to another event of textbox, named KeyPress as:
private void txtCutParagraph_KeyPress(object sender, KeyPressEventArgs e)
{
int limitNum = 30;
string sentence = txtCutParagraph.Text;
string[] words = sentence.Split(' ');
string line = "";
foreach (string word in words)
{
if ((line + word).Length > limitNum)
{
newLine += line + "\r\n";
line = "";
}
line += word + " ";
}
if (line.Length > 0)
newLine += line + "\r\n";
txtCutParagraph.Text = newLine;
}
What you are trying to do is called Word wrapping. TextBox class has Wordwrap option by default. unfortunately you cant limit number of characters per line.
You have to write an algorithm instead. I have noticed that your algorithm does not work correctly. so i decided to write one my self (as it was a good practice!). It is hard to handle all situations that can happen inside text formatting. I tried my best anyway you have to write one your self if you are not satisfied with results.
Before using this algorithm you have to disable Wordwrap feature of Textbox. So they will not Interfere each other. In InitializeComponent inside Form Designer add this line.
this.textBox1.WordWrap = false;
Now use this algorithm to do it for you! Note that textbox1 is a multi line text box.
private StringBuilder stringBuilder = new StringBuilder();
private bool _isInsideTextChanged = false;
private const int MaximumChars = 30; // Maximum characters
private StringBuilder WrapText(StringBuilder text, ref int position)
{
StringBuilder newStringBuilder = new StringBuilder(text.ToString());
int charsPerLine = 0;
int lastSpace = -1; // index of last space per line
for (int i = 0; i < newStringBuilder.Length; i++)
{
if (newStringBuilder[i] == ' ')
{
if (newStringBuilder.Length > i + 2 && newStringBuilder.ToString(i + 1, 2) == "\r\n")
{
if (newStringBuilder.Length > i + 3)
{
int next = newStringBuilder.ToString().IndexOf(' ', i + 3);
if (next != -1 && charsPerLine + next - i <= MaximumChars || charsPerLine + newStringBuilder.Length - i - 2 <= MaximumChars)
{
newStringBuilder.Remove(i + 1, 2);
if (i <= textBox1.SelectionStart)
{
position -= 2;
}
continue;
}
}
i++;
continue;
}
if (newStringBuilder.Length > i + 1 && newStringBuilder[i + 1] != ' ')
{
lastSpace = i;
}
}
if (newStringBuilder[i] == '\n' || newStringBuilder[i] == '\r')
{
lastSpace = -1;
charsPerLine = 0;
}
if (++charsPerLine > MaximumChars && lastSpace != -1)
{
newStringBuilder.Insert(lastSpace + 1, "\r\n");
if (lastSpace <= textBox1.SelectionStart)
{
position += 2;
}
charsPerLine = i - lastSpace;
lastSpace = -1;
i++;
}
}
return newStringBuilder;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (_isInsideTextChanged) return;
_isInsideTextChanged = true;
stringBuilder.Clear();
stringBuilder.Append(textBox1.Text);
int position = textBox1.SelectionStart;
string newText = WrapText(stringBuilder, ref position).ToString();
textBox1.Text = newText;
textBox1.SelectionStart = position;
_isInsideTextChanged = false;
}
Here is the test that shows the results.
How this wroks?
This algorithm will count the number of characters from last line break index (default value is 0) up to last space character index per line.(default value is -1 means no space in that line). Then it will put line break after last space if the number of characters on that line is more than 30. How ever this algorithm test other things too to better handle text formatting.
This is done every time a textbox value is changed. StringBuilder is used instead of string to increase performance.
To prevent stack overflow exception as described by #KhaksarWeqar I used a boolean value _isInsideTextChanged with TextChanged event:
private bool _isInsideTextChanged = false;
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (_isInsideTextChanged) return; // return if was inside TextChanged.
_isInsideTextChanged = true; // inside TextChanged
// Do stuff...
_isInsideTextChanged = false; // outside TextChanged
}
There is also a better way explained on wiki. you can create your own even better!. https://en.wikipedia.org/wiki/Line_wrap_and_word_wrap

PigLatin translate

I will create a program that translates English words into Pig Latin ... My problem with the code found below, is that the only word in the last index of the array as reported in the results? Does anyone see the error?
Thanks in advance
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnTrans_Click( object sender, EventArgs e )
{
string engWordText = engWord.Text.ToString();
string let1;
string restLet;
int position;
string pigLatin = "";
string vokal = "AEIOUaeiou";
// split the sentence into individual words
//string[] words = engWordText.Split(' ');
string[] transWord = engWordText.Split(' ');
// translate each word into pig latin
foreach (string word in transWord)
{
// check for empty TextBox
try
{
let1 = word.Substring(0, 1);
restLet = word.Substring(1, word.Length - 1);
position = vokal.IndexOf(let1);
if (position == -1)
{
pigLatin = restLet + let1 + "ay";
}
else
{
pigLatin = word + "way";
}
// display the translation
latinInput.Text = pigLatin.ToString();
engWord.Clear();
}
catch (System.ArgumentOutOfRangeException)
{
MessageBox.Show("Du måste skriva in ett engelskt ord", "PigLatin",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
} // end method translateButton_Click
// pressing enter is the same as clicking the Translate Button
private void engWordText_KeyDown( object sender, KeyEventArgs e )
{
// allow user to press enter in TextBox
if ( e.KeyCode == Keys.Enter )
btnTrans_Click( sender, e );
} // end method inputTextBox_KeyDown
} // end class PigLatinForm
You are assigning the value of pigLatin to the text box's Text property at the end of each loop, which means it will only have the last value that was assigned to it. Try this:
List<string> plWords = new List<string>();
// translate each word into pig latin
foreach (string word in transWord)
{
// check for empty TextBox
try
{
let1 = word[0];
restLet = word.Substring(1, word.Length - 1);
if (!vokal.Contains(let1))
{
pigLatin = restLet + let1 + "ay";
}
else
{
pigLatin = word + "way";
}
plWords.Add(pigLatin);
}
catch (System.ArgumentOutOfRangeException)
{
MessageBox.Show("Du måste skriva in ett engelskt ord", "PigLatin",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
engWord.Clear();
latinInput.Text = string.Join(" ", plWords.ToArray());
As a bit of a bonus, here's how you can make this operation quite a bit cleaner using Linq:
private static string MakePigLatin(string word)
{
const string vowels = "AEIOUaeiou";
char let1 = word[0];
string restLet = word.Substring(1, word.Length - 1);
return vowels.Contains(let1) ? word + "way" : restLet + let1 + "ay";
}
private void btnTrans_Click( object sender, EventArgs e )
{
var plWords = engWord.Text
.Split(new[]{' '}, StringSplitOptions.RemoveEmptyEntries)
.Select(MakePigLatin);
latinInput.Text = string.Join(" ", plWords);
engWord.Clear();
}

Numbered list on Richtextbox

I'm trying to add numbered list functionality to a text editor. RichTextbox already provides the SelectionBullet property to change a selection to a bulleted list. But i was unable to find a similar property to generate numbered list. Is there any standard way to create a numbered list on Richtextbox. If not, i would have to implement it myself so code snips that could help me do that will help, Thank you.
I know that a link is not gernerally accepted as a good answer, however the article RichTextBox with Search Line Numbering, Bulleting, Printing, Searching Support on CodeProject could probably help you out quite a bit with what you are looking for.
In this article, the author extends the RichTextBox control into something that can do what you are asking (and more), plus the code is posted there for all to see.
Well, i implemented it as follows.
private void btnNumbers_Click(object sender, EventArgs e)
{
string temptext = rtbMain.SelectedText;
int SelectionStart = rtbMain.SelectionStart;
int SelectionLength = rtbMain.SelectionLength;
rtbMain.SelectionStart = rtbMain.GetFirstCharIndexOfCurrentLine();
rtbMain.SelectionLength = 0;
rtbMain.SelectedText = "1. ";
int j = 2;
for( int i = SelectionStart; i < SelectionStart + SelectionLength; i++)
if (rtbMain.Text[i] == '\n')
{
rtbMain.SelectionStart = i + 1;
rtbMain.SelectionLength = 0;
rtbMain.SelectedText = j.ToString() + ". ";
j++;
SelectionLength += 3;
}
}
private void rtbMain_KeyDown(object sender, KeyEventArgs e)
{//this piece of code automatically increments the bulleted list when user //presses Enter key
int tempNum;
if (e.KeyCode == Keys.Enter)
try
{
if (char.IsDigit(rtbMain.Text[rtbMain.GetFirstCharIndexOfCurrentLine()]))
{
if (char.IsDigit(rtbMain.Text[rtbMain.GetFirstCharIndexOfCurrentLine() + 1]) && rtbMain.Text[rtbMain.GetFirstCharIndexOfCurrentLine() + 2] == '.')
tempNum = int.Parse(rtbMain.Text.Substring(rtbMain.GetFirstCharIndexOfCurrentLine(),2));
else tempNum = int.Parse(rtbMain.Text[rtbMain.GetFirstCharIndexOfCurrentLine()].ToString());
if (rtbMain.Text[rtbMain.GetFirstCharIndexOfCurrentLine() + 1] == '.' || (char.IsDigit(rtbMain.Text[rtbMain.GetFirstCharIndexOfCurrentLine() + 1]) && rtbMain.Text[rtbMain.GetFirstCharIndexOfCurrentLine() + 2] == '.'))
{
tempNum++;
rtbMain.SelectedText = "\r\n" + tempNum.ToString() + ". ";
e.SuppressKeyPress = true;
}
}
}
catch{}
}
Here is my answer... which is easily readable and refineable. I took a much different approach but added the ability to remove the numbered list within the selection if it already exists. Please note that so far I have only lightly tested it and it seems to work good... but it may need further refinement.
private void btnOrdered_Click(object sender, EventArgs e)
{
string[] splitSelection = null;
// If selection split selection else split everything
if (this.txtCaptionEditor.SelectionLength > 0)
{
splitSelection = this.txtCaptionEditor.SelectedText.Replace("\r\n", "\n").Split("\n".ToCharArray());
}
else
{
splitSelection = this.txtCaptionEditor.Text.Replace("\r\n", "\n").Split("\n".ToCharArray());
}
bool Exists = false;
for (int i = 0; i < splitSelection.GetLength(0); i++)
{
// If Ordered List Allready exists in selection then remove else add
if (!string.IsNullOrEmpty(splitSelection[i]))
{
if (splitSelection[i].Substring(0, 2) == "1.") { Exists = true; }
}
}
for (int i = 0; i < splitSelection.GetLength(0); i++)
{
int lineCount = (i + 1);
if (Exists)
{
this.txtCaptionEditor.Text = this.txtCaptionEditor.Text.Replace(Convert.ToString(lineCount) + ". ", "");
}
else
{
if(!string.IsNullOrEmpty(splitSelection[i]))
{
this.txtCaptionEditor.Text = this.txtCaptionEditor.Text.Replace(splitSelection[i], Convert.ToString(lineCount) + ". " + splitSelection[i]);
}
}
}
}
private void txtCaptionEditor_KeyDown(object sender, KeyEventArgs e)
{
string[] splitSelection = this.txtCaptionEditor.Text.Replace("\r\n", "\n").Split("\n".ToCharArray());
if (e.KeyCode == Keys.Enter)
{
// Get Current Line Position
int currentLine = this.txtCaptionEditor.GetLineFromCharIndex(this.txtCaptionEditor.SelectionStart);
// Only Run if the previous line is greater than zero
if ((currentLine) >= 0)
{
// Loop through 100 possible numbers for match you can go higher
// If you think your numbered list could go above 100
for (int i = 0; i < 100; i++)
{
if (splitSelection[(currentLine)].Substring(0, 2) == Convert.ToString((i + 1)) + ".")
{
// If the substring of the current line equals a numbered list value.. enumerate next line
this.txtCaptionEditor.SelectedText = "\n" + (i + 2) + ". ";
e.SuppressKeyPress = true;
}
}
}
}
}

Highlighting User Defined Keywords in RichTextBox

I am searching XML files to see if there are contents which match the words inserted in these textboxes txtComKeyword1, txtComKeyword2, txtComKeyword3 and/or txtComKeyword4. The function below is working, but may I know how can I highlight the keywords that user entered in the four textboxes that match that appear in my richComResults richtextbox?
For example, my user will fill in those four textboxes ie. txtComKeyword1, txtComKeyword2, txtComKeyword3 and txtComKeyword4. Then, my code will parse the XML file to see if the nodes contain these four keywords, if yes, the nodes' data will be output on my richComResults, I wanna highlight those four keywords (eg txtComKeyword1=hello, txtComKeyword2=bye, txtComKeyword3=morning, txtComKeyword4=night). These 4 words, if found and appear in richComResults, will be highlighted with color.
I have no clue after searching for a while, my case is much different from other questions. I am a newbie in programming, your help would be much appreciated. Thank you!
My Code:
private void searchComByKeywords()
{
// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(sourceDir);
foreach (string fileName in fileEntries)
{
XmlDocument xmlDoc = new XmlDocument(); //* create an xml document object.
string docPath = fileName;
xmlDoc.Load(docPath); //* load the XML document from the specified file.
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("item");
foreach (XmlNode node in nodeList)
{
XmlElement itemElement = (XmlElement) node;
string itemDescription = itemElement.GetElementsByTagName("description")[0].InnerText;
if (txtComKeyword1.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword1.Text.ToLower()) ||
txtComKeyword2.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword2.Text.ToString()) ||
txtComKeyword3.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword3.Text.ToString()) ||
txtComKeyword4.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword4.Text.ToString()))
{
string itemTitle = itemElement.GetElementsByTagName("title")[0].InnerText;
string itemDate = itemElement.GetElementsByTagName("pubDate")[0].InnerText;
string itemAuthor = itemElement.GetElementsByTagName("author")[0].InnerText;
richComResults.AppendText("Author: " + itemAuthor + "\nDate: " + itemDate + "\nTitle: " + itemTitle + "\nDescription: " + itemDescription + "\n\n--------\n\n");
}
}
}
}
Try this:
int pointer = 0;
int index = 0;
string keyword = "txtComKeyword1";
while (true)
{
index = richComResults.Text.IndexOf(keyword, pointer);
//if keyword not found
if (index == -1)
{
break;
}
richComResults.Select(index, keyword.Length);
richComResults.SelectionFont = new System.Drawing.Font(richComResults.Font, FontStyle.Bold);
pointer = index + keyword.Length;
}
This searches for the keyword and highlights it. Then it continues the search after the found keyword. The pointer is used to keep track of the search position in your text. The index marks the position of the found keyword.
Jan's answer contains great content, but I shuddered mildly at the while(true) and break aspect! Here's my tweaked (case-insensitive) version...
int nextHigh = RTF.Text.IndexOf(txSearch, 0, StringComparison.OrdinalIgnoreCase);
while (nextHigh >= 0)
{
RTF.Select(nextHigh, txSearch.Length);
RTF.SelectionColor = Color.Red; // Or whatever
RTF.SelectionFont = new Font("Arial", 12, FontStyle.Bold); // you like
nextHigh = RTF.Text.IndexOf(txSearch, nextHigh + txSearch.Length, StringComparison.OrdinalIgnoreCase);
}
try this code :
void ParseLine(string line)
{
Regex r = new Regex("([ \\t{}():;])");
String[] tokens = r.Split(line);
foreach (string token in tokens)
{
// Set the tokens default color and font.
richTextBox1.SelectionColor = Color.Black;
richTextBox1.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);
// Check whether the token is a keyword.
String[] keywords = { "Author", "Date", "Title", "Description", };
for (int i = 0; i < keywords.Length; i++)
{
if (keywords[i] == token)
{
// Apply alternative color and font to highlight keyword.
richTextBox1.SelectionColor = Color.Blue;
richTextBox1.SelectionFont = new Font("Courier New", 10, FontStyle.Bold);
break;
}
}
richTextBox1.SelectedText = token;
}
richTextBox1.SelectedText = "\n";
}
and after fill your string str with your method call my method :
string strRich =
"Author : Habib\nDate : 2012-08-10 \nTitle : mytitle \nDescription : desc\n";
Regex r = new Regex("\\n");
String[] lines = r.Split(strRich);
foreach (string l in lines)
{
ParseLine(l);
}
enjoy.

Categories

Resources