I have a .NET Winforms-based program I wrote in C# where I programmatically select text within a TextBox using the Select() method. I can see the selected text on the screen and the SelectionLength member reports an accurate amount of selected characters, but the SelectedText member doesn't contain any text:
int indexPeriod = strLectureText.IndexOfAny(terminators, indexStart);
thisTextbox.Focus();
if (indexPeriod > -1)
{
thisTextbox.Select(indexStart, (indexPeriod - indexStart) + 1);
}
else
{
thisTextbox.Select(indexStart, thisTextbox.Text.Length);
}
Log.Debug("jtext len=" + thisTextbox.SelectionLength + " txt=" + thisTextbox.SelectedText);
thisTextbox.ScrollToCaret();
What's going on?
Update Nov 16 2013
I am adding additional code per #KingKing's request:
delegate void delegateMoveToNextTextFragment(ref TextBox thisTextbox, char[] terminators);
private void MoveToNextTextFragment(ref TextBox thisTextbox, char[] terminators)
{
string strLectureText = String.Empty;
strLectureText = thisTextbox.Text;
int currentStartPos = thisTextbox.SelectionStart + thisTextbox.SelectionLength - 1
// search the rest of the buffer after the currently-selected string to find the next period
int skipLastChar = 0;
// don't include last selected character in search
try
{
if ((thisTextbox.SelectionLength > 0) & (strLectureText[currentStartPos] != '.'))
{
skipLastChar = 1;
}
}
catch (Exception ex)
{
Debug.WriteLine("exception caught! ex=" + ex.Message);
skipLastChar = 0;
}
int indexStart = 0;
if (currentStartPos == 0)
{
indexStart = 0;
}
else
{
indexStart = currentStartPos + 1;
}
int indexPeriod = strLectureText.IndexOfAny(terminators, indexStart);
if (indexPeriod > -1)
{
thisTextbox.Select(indexStart, (indexPeriod - indexStart) + 1);
}
else
{
thisTextbox.Select(indexStart, thisTextbox.Text.Length);
}
thisTextbox.Focus();
Log.Debug("jtext len=" + thisTextbox.SelectionLength + " txt=" + thisTextbox.SelectedText);
thisTextbox.ScrollToCaret();
}
Related
I created a program that uses both linear and binary search method. I use string array.
private void linearSearch_Click(object sender, EventArgs e)
{
string target = linearSearchBox.Text;
bool found = false;
for (int x = 0; x < myArray.Length; x++)
{
if (myArray[x] == target)
{
displayBox2.Text = target + " Found at index " + (x + 1) +
"\r\n";
linearSearchBox.Clear();
linearSearchBox.Focus();
return;
}
}
if (!found)
{
displayBox2.Text = "Not Found, try again." + "\r\n";
linearSearchBox.Clear();
linearSearchBox.Focus();
}
}
this will work, however the binary doest not
private void BinarySearch_Click(object sender, EventArgs e)
{
Array.Sort(myArray, 0, emptyPtr);
SearchArray(myArray, binarySearchBox.Text);
}
private void SearchArray(Array array, object value)
{
Array.Sort(myArray, 0, emptyPtr);
string target = binarySearchBox.Text;
int numIndex = Array.BinarySearch(array, target);
if (numIndex < 0)
{
displayBox2.Text = "The element to search for " + target + " is not found.";
}
else if(numIndex >= 0)
{
displayBox2.Text = "The element to search for " + target+ " is at index: " + numIndex;
}
}
test1 test2
Note that the code is performing a binary search in the text box of binarySearchBox, not the value in the text box of ListBox1.
The code that needs to convert the value added to ListBox1 into an Array array for storage.string[]myArray = listBox1.Items.Cast<string>().ToArray();,then search for ListBox1.
Code show as below:
private void BinarySearch_Click(object sender, EventArgs e)
{
string[]myArray = listBox1.Items.Cast<string>().ToArray();
Array.Sort(myArray, 0, emptyPtr);
SearchArray(myArray, binarySearchBox.Text);
}
private void SearchArray(Array array, object value)
{
string[] myArray = listBox1.Items.Cast<string>().ToArray();
Array.Sort(myArray, 0, emptyPtr);
string target = binarySearchBox.Text;
int numIndex = Array.BinarySearch(array, target);
if (numIndex < 0)
{
displayBox2.Text = "The element to search for " + target + " is not found.";
}
else if (numIndex >= 0)
{
displayBox2.Text = "The element to search for " + target + " is at index: " + numIndex;
}
}
private void linearSearch_Click(object sender, EventArgs e)
{
string[] myArray = listBox1.Items.Cast<string>().ToArray();
string target = linearSearchBox.Text;
bool found = false;
for (int x = 0; x < myArray.Length; x++)
{
if (myArray[x] == target)
{
displayBox2.Text = target + " Found at index " + (x + 1) +
"\r\n";
linearSearchBox.Clear();
linearSearchBox.Focus();
return;
}
}
if (!found)
{
displayBox2.Text = "Not Found, try again." + "\r\n";
linearSearchBox.Clear();
linearSearchBox.Focus();
}
}
I am trying to highlight words in richtextbox. When user mouse over the word in richtextbox the word should be highlighted.
Below is the code I am so far. Errors: last highlight point is good but start point is not accurate, When i place a new paragrah or new line then start point goes so away then expected result.
private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
{
richTextBox1.Focus();
selectWordOnMouseOver();
}
public void selectWordOnMouseOver()
{
if (richTextBox1 == null)
return;
TextPointer cursurPosition = richTextBox1.GetPositionFromPoint(Mouse.GetPosition(richTextBox1), false);
if (cursurPosition == null)
return;
int offset = richTextBox1.Document.ContentStart.GetOffsetToPosition(cursurPosition);
// offset = offset;
//MessageBox.Show("Offset = " + offset.ToString());
int spaceAfter = FindSpaceAfterWordFromPosition(cursurPosition, " ");
int spaceBefore = FindSpaceBeforeWordFromPosition(cursurPosition, " ");
TextPointer wholeText = richTextBox1.Document.ContentStart;
TextPointer start = wholeText.GetPositionAtOffset(spaceBefore);
TextPointer end = wholeText.GetPositionAtOffset(spaceAfter);
if (start == null || end == null )
return;
richTextBox1.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
richTextBox1.Selection.Select(start, end);
// MessageBox.Show("Mouse Over On = " + offset.ToString() + ": Word Start = " + (spaceBefore).ToString() + ": Word End = " + (spaceAfter).ToString() + " : Word is = " + richTextBox1.Selection.Text);
}
int FindSpaceBeforeWordFromPosition(TextPointer position, string word)
{
while (position != null)
{
if (position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text)
{
string textRun = position.GetTextInRun(LogicalDirection.Backward);
// Find the starting index of any substring that matches "word".
int spaceIndexBeforeMouseOver = textRun.LastIndexOf(word);
return spaceIndexBeforeMouseOver;
}
position = position.GetNextContextPosition(LogicalDirection.Backward);
}
// position will be null if "word" is not found.
return 0;
}
int FindSpaceAfterWordFromPosition(TextPointer position, string word)
{
while (position != null)
{
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
string textRun = position.GetTextInRun(LogicalDirection.Forward);
// Find the starting index of any substring that matches "word".
int spaceIndexAfterMouseOver = textRun.IndexOf(word);
int lastIndexAfterMouseOverIndex = textRun.Count();
int mouseOverIndex = richTextBox1.Document.ContentStart.GetOffsetToPosition(position);
if (spaceIndexAfterMouseOver >= 0)
{
return spaceIndexAfterMouseOver + mouseOverIndex;
}
else//if space index not found the select to to the last word of text box
return mouseOverIndex + lastIndexAfterMouseOverIndex;
}
position = position.GetNextContextPosition(LogicalDirection.Forward);
}
// position will be null if "word" is not found.
return 0;
}
results when no new line.
results when there are 3 new line feeds.
UPDATE 1:
I recently after testing found one thing that I am getting wrong offset.
Point nMousePositionCoordinate = Mouse.GetPosition(richTextBox1);
// System.Diagnostics.Debug.WriteLine(nMousePositionCoordinate.ToString());
TextPointer cursurPosition = richTextBox1.GetPositionFromPoint(nMousePositionCoordinate, false);
if (cursurPosition == null)
return;
int offset = richTextBox1.Document.ContentStart.GetOffsetToPosition(cursurPosition);
System.Diagnostics.Debug.WriteLine(offset.ToString());
I am working on a Reverse polish notation calculator. I created a method that will take care of the calculations but there are three lines in my code that are causing an error. After every = an operation is performed and then displayed. I am trying to grab the string from TxtInputBox and convert to integers but it always shows the catch message Please check the input. Then nothing gets calculated or display. I am sure that my first if statement will check for actual integers and avoid the characters. My ultimate goal is to input a formula in rpn format and have the result display in the multiline textbox.
Sample Input 5 6 -=
Code
namespace rpncalc
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void RPNCalc(TextBox TxtBoxInputbox, TextBox TxtBoxOutputbox)
{
Stack<int> stackone = new Stack<int>();
stackone.Clear();
string[] inputarray = TxtBoxInputbox.Text.Split();
int end = inputarray.Length - 1;
int numinput;
int i = 0;
do
{
if(inputarray[i] != "=" && inputarray[i] != "+" && inputarray[i] != "-" && inputarray[i] != "*" && inputarray[i] != "/")
{
try
{
numinput = Convert.ToInt32(inputarray[i]);
stackone.Push(numinput);
}
catch
{
MessageBox.Show("Please check the input");
}
}
else if (inputarray[i]== "+")
{
try
{
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 + store1);
}
catch
{
}
}
else if (inputarray[i]== "-")
{
try
{
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 + store1);
}
catch
{
}
}
else if (inputarray[i]== "+")
{
try
{
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 + store1);
}
catch
{
}
}
else if (inputarray[i]== "*")
{
try
{
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 + store1);
}
catch
{
}
}
else if (inputarray[i]== "/")
{
try
{
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 + store1);
}
catch
{
}
}
}
while(i < end && inputarray[i]!= "=" && stackone.Count != 0);
string txtout = TxtInputBox + " " + stackone.Pop().ToString() + Environment.NewLine;
TxtOutputBox.AppendText(txtout);
TxtInputBox.Clear();
}
private void Btn_Calc_Click(object sender, EventArgs e)
{
RPNCalc(TxtInputBox, TxtOutputBox);
}
}
}
The Split command, with no argument, is splitting the string on spaces and other whitespace.
There is no space in the input between -= so it is treated as one token that doesn't match the tests in the if statement.
Original answer incorrectly suggested that Split with no argument was splitting into individual characters.
What are you doing to increment i after each iteration of your do loop? I tried out your code and it seems like i is never incremented. Also, when you catch and run
catch
{
MessageBox.Show("Please check the input");
}
You could perhaps change it to:
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
so you could be sure of just what you're catching, and why.
Edit:
Here's my version of your code, now working correctly:
i is incremented in each iteration
Fixed the typo in the minus, multiplication and division operators that made them do addition instead
Removed the redundant addition operator
namespace rpncalc {
public partial class Form1 : Form {
public Form1 () {
InitializeComponent();
}
private void RPNCalc (TextBox TxtBoxInputbox, TextBox TxtBoxOutputbox) {
Stack<int> stackone = new Stack<int>();
stackone.Clear();
string[] inputarray = TxtBoxInputbox.Text.Split();
int end = inputarray.Length - 1;
int numinput;
int i = 0;
do {
if (inputarray[i] != "=" && inputarray[i] != "+" && inputarray[i] != "-" && inputarray[i] != "*" && inputarray[i] != "/") {
try {
numinput = Convert.ToInt32(inputarray[i]);
stackone.Push(numinput);
} catch (Exception e) {
MessageBox.Show(e.ToString());
}
} else if (inputarray[i] == "+") {
try {
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 + store1);
} catch {
}
} else if (inputarray[i] == "-") {
try {
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 - store1);
} catch {
}
} else if (inputarray[i] == "*") {
try {
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 * store1);
} catch {
}
} else if (inputarray[i] == "/") {
try {
int store1 = stackone.Pop();
int store2 = stackone.Pop();
stackone.Push(store2 / store1);
} catch {
}
}
}
while (i++ < end && inputarray[i] != "=" && stackone.Count != 0);
string txtout = TxtInputBox.Text + " " + stackone.Pop().ToString() + Environment.NewLine;
TxtOutputBox.AppendText(txtout);
TxtInputBox.Clear();
}
private void Btn_Calc_Click (object sender, EventArgs e) {
RPNCalc(TxtInputBox, TxtOutputBox);
}
}
}
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;
}
}
}
}
}
I am trying to check for ascending order in this array
But not sure how to use a foreach
foreach (double d in dSize)
{
if (dSize.ToString() != null)
{
double dSize1;
string str1 = dSize.ToString();
bool success1 = double.TryParse(str1, out dSize1);
if ( dSize < 0.0)
{
errMsg1 = " data grid should contain number >= 0";
}
//else
//{
// errMsg1 = " data grid must be entered";
//}
}
*if (inputs.dSize[rowCount] <= inputs.dSize[rowCount - 1])
{
errMsg = "value in row " + (rowCount + 1) + " should be greater than the value in row " + rowCount;
}
}*
swRpt.WriteLine(errMsg);
}
I've done the second part using a for loop. Would like to change it to a foreach
You just need to remember the previous value from one iteration to the next. The issue with using foreach for this (as opposed to the raw iterator) is that you need a special case for the first value:
Double lastDouble = null;
foreach(double d in dSize) {
if ((lastDouble != null) && (lastDouble > d)) {
errMsg = "value out of sequence";
break;
}
lastDouble = d;
}
but then you've lost the row number for the error. You could also prime your last value from the first entry and skip one using LINQ
double lastDouble = dSize.First();
foreach(double d in dSize.Skip(1)) {
if (lastDouble > d) {
errMsg = "value out of sequence";
break;
}
lastDouble = d;
}
Why not...
for(int i = dSize.Length-1; i>=0;i--)
{
double d = dSize[i];
...
...
...
}