I am developing a simple text editor, and I'm having trouble doing the self add some character ... I did the following sample code, what I'm doing ... When I type the character, it does not add its corresponding char in current cursor position....
Another doubt, how can I make the program ignore the characters added when I type it again ...??
Dictionary<char, char> glbin = new Dictionary<char, char>
{
{'(', ')'},
{'{', '}'},
{'[', ']'},
{'<', '>'}
};
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
int line = textBox1.GetLineFromCharIndex(textBox1.SelectionStart);
int column = textBox1.SelectionStart - textBox1.GetFirstCharIndexFromLine(line);
if(glbin.ContainsKey(e.KeyChar))
textBox1.Text.Insert(column, glbin[e.KeyChar].ToString());
}
String is immutable object, and Insert call on Text property produces new instance of string, which is not assigned anywhere.
And to ignore char you need to set KeyPressEventArgs Handled property to true (you would probably need inverse dictionary of closing chars).
You need to change your code to:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
int index = textBox1.SelectionStart;
if(glbin.ContainsKey(e.KeyChar))
{
var txt = textBox1.Text; // insert both chars at once
textBox1.Text = txt.Insert(index, e.KeyChar + glbin[e.KeyChar].ToString());
textBox1.Select(index + 1, 0);// position cursor inside brackets
e.Handled = true;
}
else if (glbin.Values.Contains(e.KeyChar))
{
// move cursor forward ignoring typed char
textBox1.SelectionStart = textBox1.SelectionStart + 1;
e.Handled = true;
}
}
Related
I have textbox that I managed to accept numbers only by KeyPress but I cannot make input numbers separated by commas.
private void inputAmount_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.'))
{
e.Handled = true;
// this doesn't work
inputAmount.Text = string.Format("{0:#,##}", e.KeyChar);
}
}
What I'm looking for is: when user starts typing numbers in text box it separate thousands by commas while user typing.
Any idea?
Update
I've added second function TextChanged as following and removed inputAmount.Text = string.Format("{0:#,##}", e.KeyChar); line from code above.
It does add thousands separators to my input but it keeps jumping to beginning of the numbers
private void inputAmount_TextChanged(object sender, EventArgs e)
{
inputAmount.Text = string.Format("{0:#,##0}", double.Parse(inputAmount.Text));
}
Solved
Here is my final code that solved the issue
// Only accept numbers
private void inputAmount_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.'))
{
e.Handled = true;
}
}
// Add thousand separators while user typing
private void inputAmount_TextChanged(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(inputAmount.Text))
{
System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");
int valueBefore = Int32.Parse(inputAmount.Text, System.Globalization.NumberStyles.AllowThousands);
inputAmount.Text = String.Format(culture, "{0:N0}", valueBefore);
inputAmount.Select(inputAmount.Text.Length, 0);
}
}
Check with int.TryParse whether the input text is a number .
Then add the inputAmount string with the current character and convert it to the desired format.
Then place the CaretIndex at the end of the control with inputAmount.SelectionStart.
The following code shows how to do this
private void inputAmount_KeyPress(object sender, KeyPressEventArgs e)
{
int number = 0;
bool success = int.TryParse(e.KeyChar.ToString(), out number);
if (success)
{
string input = (inputAmount.Text + e.KeyChar).Replace(",", "");
inputAmount.Text = String.Format("{0:n0}", Convert.ToInt32(input));
inputAmount.SelectionStart = inputAmount.Text.Length;
e.Handled = true;
}
}
I'm new to C#. Using the code below, whenever I press a number key on my keyboard, it will display twice in the textbox. When I press "1" on the keyboard it will display
"11", and when I press "2" it will display "22". Why is this?
private void Window_TextInput(object sender, TextCompositionEventArgs e)
{
if(!isNumeric(e.Text))
{
string display = string.Empty;
display += e.Text;
displayNum(display);
}
else
{
String inputOperator = string.Empty;
inputOperator += e.Text;
if (inputOperator.Equals("+"))
{
ApplySign(sign.addition, "+");
}
}
}
private bool isNumeric(string str)
{
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("[^0-9]");
return reg.IsMatch(str);
}
private void window_keyUp(object sender, KeyEventArgs e)
{
if (e.Key >= Key.D0 && e.Key <= Key.D9)
{
int num = e.Key - Key.D0;
outputText2.Text += num;
}
}
private void BtnNum_Click(object sender, RoutedEventArgs e)
{
Button num = ((Button)sender);
displayNum(num.Content.ToString());
}
private void displayNum(String n)
{
if (operator1 == 0 && double.Parse(n) == 0)
{
}
else
{
if (operator1 == 0)
{
outputText2.Clear();
}
outputText2.Text += n;
operator1 = double.Parse(outputText2.Text);
outputText2.Text = Convert.ToString(operator1);
}
}
You have two events that are handeling the Keyboard events. Although not really sure what the displayNum() method is doing
I am assuming the Window_TextInput event is the event you wish to primarily handle the event.
Try adding
e.Handled = true;
In the Window_TextInput method. If that doesn't solve the problem can you post the displayNum() method?
EDIT:
After further review of the code and trying the same I do not see the relevance for the window_keyUp method as your Window_TextInput handles the input characters and has more applicable logic for handling the TextInput changes.
After I removed the window_keyUp event method the output appeared as expected (although commented out the ApplySign() method.
You've subscribed to two window-level text-related events - TextInput and KeyUp - and both of them end up appending input to the TextBox.
window_keyUp appends numbers to the TextBox
It looks like Window_TextInput is supposed to append non-numeric characters, but your RegEx is incorrect ([^0-9] matches anything that is not numeric, so IsNumeric returns True if the input is not a number)
The effect is that every numeric key press shows up twice.
I have a button on a c# form that when it is clicked, should change its text value to the next letter in the alphabet sequence.
The default button value is a dash "-" (when the application starts). When the button is clicked, it should change to A, and when it's click again, change to B. At Z, it should reset to A.
I have the following code, however, when the button is pressed, it just returns an open bracket "[".
private void alphaCode_Click(object sender, EventArgs e)
{
string s = null;
for (char c2 = 'A'; c2 <= 'Z' + 1; c2++)
{
s = c2.ToString();
}
alphaCode.Text = s;
}
You do not need a loop in the alphaCode_Click, because the cycle happens outside of the "on click" event handler. It's the user who does the looping (by clicking a button); your code performs a single step of that loop.
Therefore, all you need is to pick the letter from the alphaCode.Text, add one to it, and set it back into the alphaCode.Text field:
private void alphaCode_Click(object sender, EventArgs e)
{
string s = null;
var current = alphaCode.Text.Length == 1 ? alphaCode.Text[0] : 'A';
if (current >= 'A' && current <= 'Z') {
current++;
} else {
current = 'A';
}
alphaCode.Text = "" + current;
}
A solution that does not depend on the current text value and works for any alphabet:
string const Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int _currentCharacterIndex = -1;
private void alphaCode_Click(object sender, EventArgs e)
{
_currentCharacterIndex = (_currentCharacterIndex +1) % Alphabet.Count;
alphaCode.Text = Alphabet[_currentCharacterIndex ];
}
(Untested. I don't have access to Visual Studio right now.)
You are enumerating through all the letters as soon as the button is pressed. Basically, you only want to advance your character once per press.
private void alphaCode_Click(object sender, EventArgs e)
{
char currentChar = alphaCode.Text[0];
if(currentChar == '-')
{
alphaCode.Text = "A";
}
else
{
char newChar = currentChar + 1;
if(newChar > 'Z')
{
newChar = 'A';
}
alphaCode.Text = newChar;
}
}
Use the ASCII code of current text as tag for the button. On each click, increase it and change the text. Now, once you have moved through the range (Z that is), reset to a.
Are you dealing with both uppercase and lowercase?
private void alphaCode_Click(object sender, EventArgs e)
{
char s = Convert.ToChar(alphaCode.Text.Trim());
if (s == '-' || s == 'Z')
{
alphaCode.Text = "A";
}
else
{
s++;
alphaCode.Text = s.ToString();
}
}
The char Z is the 90th (dec) in the ASCII table, so when you loop until 90 + 1 = 91, and assign the textBox to it, it shows '[' which is the 91th. For the sake of simplicity, have a char created as a field (within the class, not any function or procedure), and everytime the user clicks you just assign the textbox to the current value and then increment it.
private void alphaCode_Click(object sender, EventArgs e)
{
txtAlph.Text = currentChar.ToString();
currentChar++;
}
Then, as a field, just use a char to hold the value:
char currentChar = 'A';
Set your char as an field. And increase the value of c with every buttonclick. If c = Z then start again on A...
char c = 'A';
private void button_Click(object sender, EventArgs e) {
if(c == 'Z'){
c = 'A';
}
label1.Text = c + "";
c++;
}
Just loop through the char code
public partial class Form1 : Form
{
private int _charCode = 65;
public Form1()
{
InitializeComponent();
alphaCode.Text = "-";
}
private void alphaCode_Click(object sender, EventArgs e)
{
// 90 is 'Z'
if (_charCode > 90)
_charCode = 65;
alphaCode.Text = ((char)_charCode).ToString();
_charCode++;
}
}
I would like to change all the characters entered into a textbox to upper case. The code will add the character, but how do I move the caret to the right?
private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
{
textBox3.Text += e.KeyChar.ToString().ToUpper();
e.Handled = true;
}
Set the CharacterCasing property of the TextBox to Upper; then you don't need to process it manually.
Note that textBox3.Text += e.KeyChar.ToString().ToUpper(); will append the new character to the end of the string even if the input caret is in the middle of the string (which most users will find highly confusing). For the same reason we cannot assume that the input caret should appear at the end of the string after inputting the character.
If you would still really want to do this in code, something like this should work:
// needed for backspace and such to work
if (char.IsControl(e.KeyChar))
{
return;
}
int selStart = textBox3.SelectionStart;
string before = textBox3.Text.Substring(0, selStart);
string after = textBox3.Text.Substring(before.Length);
textBox3.Text = string.Concat(before, e.KeyChar.ToString().ToUpper(), after);
textBox3.SelectionStart = before.Length + 1;
e.Handled = true;
tbNumber.SelectionStart = tbNumber.Text.ToCharArray().Length;
tbNumber.SelectionLength = 0;
private void txtID_TextChanged(object sender, EventArgs e)
{
txtID.Text = txtID.Text.ToUpper();
txtID.SelectionStart = txtID.Text.Length;
}
This will preserve the location of the insertion point (but persionally I'd go with the answer given by Fredrik Mörk)
private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
{
int selStart = textBox3.SelectionStart;
textBox3.Text += e.KeyChar.ToString().ToUpper();
textBox3.SelectionStart = selStart;
e.Handled = true;
}
SelectionStart might actually be called SelStart, I don't have a compiler handy at the moment.
If you have to do this manually, you can use
private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
{
textBox3.Text += e.KeyChar.ToString().ToUpper();
textBox3.SelectionStart = textBox3.Text.Length;
e.Handled = true;
}
But the preceding code inserts the new character at the end of the text. If you want to insert it at where the cursor is:
private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
{
int selStart = textBox3.SelectionStart;
textBox3.Text = textBox3.Text.Insert(selStart,e.KeyChar.ToString().ToUpper());
textBox3.SelectionStart = selStart + 1;
e.Handled = true;
}
This code inserts the new character at the cursor position and moves the cursor to the left of the newly inserted character.
But i still think setting CharacterCasing is better.
Another method is to just change the value of the KeyChar itself:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e) {
if ((int)e.KeyChar >= 97 && (int)e.KeyChar <= 122) {
e.KeyChar = (char)((int)e.KeyChar & 0xDF);
}
}
Although, using the CharacterCasing property is the easiest solution.
How can I allow the users of my program to type in a value and have it auto-complete, however, I also what to prevent them from entering new data because it would cause the data to be unfindable (unless you had direct access to the database).
Does anyone know how to do this?
The reasoning behind not using just a dropdown style combobox is because entering data by typing it is and then refusing characters that are not part of an option in the list is because it's easier on the user.
If you have used Quickbook's Timer, that is the style of comboboxes I am going for.
Kudos to BFree for the help, but this is the solution I was looking for. The ComboBox is using a DataSet as it's source so it's not a custom source.
protected virtual void comboBoxAutoComplete_KeyPress(object sender, KeyPressEventArgs e) {
if (Char.IsControl(e.KeyChar)) {
//let it go if it's a control char such as escape, tab, backspace, enter...
return;
}
ComboBox box = ((ComboBox)sender);
//must get the selected portion only. Otherwise, we append the e.KeyChar to the AutoSuggested value (i.e. we'd never get anywhere)
string nonSelected = box.Text.Substring(0, box.Text.Length - box.SelectionLength);
string text = nonSelected + e.KeyChar;
bool matched = false;
for (int i = 0; i < box.Items.Count; i++) {
if (((DataRowView)box.Items[i])[box.DisplayMember].ToString().StartsWith(text, true, null)) {
matched = true;
break;
}
}
//toggle the matched bool because if we set handled to true, it precent's input, and we don't want to prevent
//input if it's matched.
e.Handled = !matched;
}
This is my solution, I was having the same problem and modify your code to suit my solution using textbox instead of combobox, also to avoid a negative response after comparing the first string had to deselect the text before comparing again against autocomplet list, in this code is an AutoCompleteStringCollection shiper, I hope this solution will help
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
String text = ((TextBox)sender).Text.Substring(
0, ((TextBox)sender).SelectionStart) + e.KeyChar;
foreach(String s in this.shippers)
if (s.ToUpperInvariant().StartsWith(text.ToUpperInvariant()) ||
e.KeyChar == (char)Keys.Back || e.KeyChar == (char)Keys.Delete)
return;
e.Handled = true;
}
OK, here's what I came up with. Hack? Maybe, but hey, it works. I just filled the combobox with the days of the week (hey, I needed something), and then handle the keypress event. On every key press, I check if that word matches the begining of any word in the AutoCompleteSourceCollection. If it doesn't, I set e.Handled to true, so the key doesn't get registered.
public Form5()
{
InitializeComponent();
foreach (var e in Enum.GetValues(typeof(DayOfWeek)))
{
this.comboBox1.AutoCompleteCustomSource.Add(e.ToString());
}
this.comboBox1.KeyPress += new KeyPressEventHandler(comboBox1_KeyPress);
}
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
{
string text = this.comboBox1.Text + e.KeyChar;
e.Handled = !(this.comboBox1.AutoCompleteCustomSource.Cast<string>()
.Any(s => s.ToUpperInvariant().StartsWith(text.ToUpperInvariant()))) && !char.IsControl(e.KeyChar);
}
EDIT: If you're on .Net 3.5 you'll need to reference System.Linq. If you're on .NET 2.0 then use this instead:
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
{
string text = this.comboBox1.Text + e.KeyChar;
foreach (string s in this.comboBox1.AutoCompleteCustomSource)
{
if (s.ToUpperInvariant().StartsWith(text.ToUpperInvariant()))
{
return;
}
}
e.Handled = true;
}
I know I'm about six years late but maybe this can help somebody.
private void comboBox1_Leave(object sender, EventArgs e)
{
if (comboBox1.Items.Contains(comboBox1.Text)) { MessageBox.Show("YE"); }
else { MessageBox.Show("NE"); }
OR
if (comboBox1.FindStringExact(comboBox1.Text) > -1) { MessageBox.Show("YE"); }
else { MessageBox.Show("NE"); }
}