I have magnetic card reader, It emulates Keyboard typing when user swipes card. I need to handle this keyboard typing to one string, when my WPF window is Focused. I can get this typed Key list, but I don't know how to convert them to one string.
private void Window_KeyDown(object sender, KeyEventArgs e)
{
list.Add(e.Key);
}
EDIT: Simple .ToString() method not helps. I've tried this already.
Rather than adding to a list why not build up the string:
private string input;
private bool shiftPressed;
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
{
shiftPressed = true;
}
else
{
if (e.Key >= Key.D0 && e.Key <= Key.D9)
{
// Number keys pressed so need to so special processing
// also check if shift pressed
}
else
{
input += e.Key.ToString();
}
}
}
private void Window_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
{
shiftPressed = false;
}
}
Obviously you need to reset input to string.Empty when you start the next transaction.
...or you can try this:
string stringResult = "";
list.ForEach(x=>stringResult+=x.ToString());
EDIT:
After good Timur comment I decided to suggest this:
you can use keyPress event to everything like this:
string stringResult = "";
private void Window_KeyPress(object sender, KeyPressEventArgs e)
{
stringResult += e.KeyChar;
}
Listen To PreviewTextInput Event Instead ...
the TextCompositionEventArgs has a property called "Text" which give you the text representation for key
for example Key.D2 will be just "2" ...i think it will
do the purpose
private void MainWindow_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
list.Add(e.Text);
}
You could have a member variable which is a StringBuilder.
something like
class A
{
StringBuilder _contents = new StringBuilder();
private void Window_KeyDown(object sender, KeyEventArgs e)
{
_contents.Append(e.Key.ToString());
}
}
You would have to create a new StringBuilder each time a new card was swiped and then to get the string you would use _contents.ToString();
String combined = String.Empty;
private void Window_KeyDown(object sender, KeyEventArgs e)
{
combined = combined + e.Key.ToString();
}
Related
Instead of copying and pasting for each number is there a method that could reference to all buttons?
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.D5)
{
Five.PerformClick();
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.D5)
{
Five.PerformClick();
}
}
Firstly, the enum values Keys.D0 to Keys.D9 have sequential integer values. You can abuse this knowledge to turn the KeyCode directly into an array index.
var buttons = new Button[] {Zero, One, ... etc ...};
if(e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9){
var index = (int)e.KeyCode - (int)Keys.D0;
var button = buttons[index];
button.PerformClick();
}
if(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9){
// similar to the above
}
Or you could rearrange your code. Create a separate method for doing the work of "user entered a digit". Then call that method from both the button click event and form key event.
private void HandleDigit(int value){
// todo
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9){
var value = (int)e.KeyCode - (int)Keys.D0;
HandleDigit(value);
}
}
Maybe this can give you an idea -- instead of the code you show something like
Button.PerformClick('5');
would do what you want. Or even
Button.PerformNumberClick(5);
and if + is preseed
Button.PerformOperatorClick('+');
You can create and event for the first button and then tie all the calculator buttons to that event, inside the event you know what key (number) is pressed.
Here is a code that could be useful, i only added two buttons to test it and notice when i live the form im releasing handles unsubscribing the events:
using System;
using System.Windows.Forms;
namespace Calculator
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
CmdButton1.KeyDown += CmdButtonKeyDown;
CmdButton2.KeyDown += CmdButtonKeyDown;
}
private void CmdButtonKeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode==Keys.NumPad1 || e.KeyCode == Keys.NumPad2 )
MessageBox.Show("KeyPressed is " + e.KeyCode.ToString());
}
private void Form1_Leave(object sender, EventArgs e)
{
CmdButton1.KeyDown -= CmdButtonKeyDown;
CmdButton2.KeyDown -= CmdButtonKeyDown;
}
}
}
I have a question. Examples that i find is on a "KeyPress" and they are not longer working on WPF
Can you tell me, how to allow only specified keys from keybord to be write on WPF textbox? I know about keyUp and Down functions, but how to define letters that i want to by type into it?
I think it will be easier, if i will post my code and i tell u what i want to do. What to change here?
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
//something here to only allow "A" key to be pressed and displeyed into textbox
if (e.Key == Key.A)
{
stoper.Start();
}
}
private void textBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.A)
{
//here i stop the stopwatch to count time of pressing the key
stoper.Stop();
string aS = stoper.ElapsedMilliseconds.ToString();
int aI = Convert.ToInt32(aS);
stoper.Reset();
}
}
You can use PreviewKeyDown and use e.Key to filter out what you need.
Or, in any place of your code you can use Keyboard class:
if (Keyboard.IsKeyDown(Key.E)) { /* your code */ }
UPDATE:
To forbid a key, you need to set event as handled:
if (e.Key == Key.E)
{
e.Handled = true;
MessageBox.Show($"{e.Key.ToString()} is forbidden");
}
That thing works pretty fine to me (thanks for #JohnyL):
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
//something here to only allow "A" key to be pressed and displeyed into textbox
if (e.Key == Key.A)
{
stoper.Start();
}
else
e.Handled = true;
}
private void textBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.A)
{
//here i stop the stopwatch to count time of pressing the key
stoper.Stop();
string aS = stoper.ElapsedMilliseconds.ToString();
int aI = Convert.ToInt32(aS);
stoper.Reset();
}
}
I have a textbox and a button.I'm saving the value(keyboard key) entered in the TextBox.I need to give a message when I press the right keyboard key.
private void btn_Click(object sender, EventArgs e)
{
Properties.Settings.Default.text1 = text1.Text;
Properties.Settings.Default.Save();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == text1.Text) //--------->> error
{
MessageBox.Show("success");
}
}
how can I provide this condition?
maybe easier it will be to use KeysConverter
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
KeysConverter convertor = new KeysConverter();
string keyPressed = convertor.ConvertToString(e.KeyValue);
if (keyPressed == text1.Text)
{
//do stuff
}
}
If you compare with one char text. You can try this.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (txt.Text.Length == 1 && e.KeyValue == (int)txt.Text[0]) //--------->> error
{
MessageBox.Show("success");
}
}
I have a code like below
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
if (!textBox1.AcceptsReturn)
{
button1.PerformClick();
}
}
}
After I hit Enter, it'll send a message to another textbox and begin a new line. Can anyone help me to bring the cursor back to its first line?
I tried textBox1.SelectionStart, SelectionLength and Focus but it doesn't work, is there any another way?
You can prevent that the keypress is passed on to the control by setting the KeyPressEventArgs.Handled property to true:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
if (!textBox1.AcceptsReturn)
{
button1.PerformClick();
e.Handled = true;
}
}
}
As you mentioned in a comment that you are implementing a chat app, you also might want to implement the typical behavior of Shift+Return inserting a new line:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == 13 && !e.Shift)
{
if (!textBox1.AcceptsReturn && !string.IsNullOrEmpty(textBox1.Text))
{
button1.PerformClick();
textBox1.Text = "";
e.Handled = true;
}
}
}
To set cursor position to the beginning of a textbox, use the following...
I will hazard a guess that you didn't use these in combination with each other...
textBox1.SelectionStart = 0;
textBox1.SelectionLength = 0;
This is the code I currently have:
private void textBox_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar) && e.KeyChar != '.';
if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1) e.Handled = true;
}
KeyPress isn't good enough to do this kind of validation. A simple way to bypass it is to paste text into the text box with Ctrl+V. Or the context menu, no key event at all.
In this specific case, the TextChanged event will get the job done:
private void textBox_TextChanged(object sender, EventArgs e) {
var box = (TextBox)sender;
if (box.Text.StartsWith(".")) box.Text = "";
}
But there's a lot more to validating numeric values. You also need to reject stuff like 1.1.1 or 1.-2 etcetera. Use the Validating event instead. Drop an ErrorProvider on the form and implement the event like this:
private void textBox_Validating(object sender, CancelEventArgs e) {
var box = (TextBox)sender;
decimal value;
if (decimal.TryParse(box.Text, out value)) errorProvider1.SetError(box, "");
else {
e.Cancel = true;
box.SelectAll();
errorProvider1.SetError(box, "Invalid number");
}
}
You probably want to use the TextChanged event, since the user could paste in values. For the best experience given the requirements, I'd suggest simply removing any leading . characters.
void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text.StartsWith("."))
{
textBox1.Text = new string(textBox1.Text.SkipWhile(c => c == '.').ToArray());
}
}
This does not address a requirement to use only digits -- wasn't clear in the question if that is the case.
This works for copy and pasting too.
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
int decimalCount=0;
string rebuildText="";
for(int i=0; i<textBox1.Text.Length; i++)
{
if (textBox1.Text[i] == '.')
{
if (i == 0) break;
if (decimalCount == 0)
rebuildText += textBox1.Text[i];
decimalCount++;
}
else if ("0123456789".Contains(textBox1.Text[i]))
rebuildText += textBox1.Text[i];
}
textBox1.Text = rebuildText;
textBox1.SelectionStart = textBox1.Text.Length;
}
You can try this:
private void TextBox_TextChanged(object sender, EventArgs e)
{
TextBox.Text = TextBox.Text.TrimStart('.');
}