How to remap keyboard keys - c#

I am trying to create an application that changes the value of the button that has been pressed.
Example: If the C button on the keyboard has been pressed then it should output the value of '7'. The buttons value should only change for as long as the application is running.
My code so far:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.KeyDown += new KeyEventHandler( Form1_KeyDown );
}
void Form1_KeyDown( object sender, KeyEventArgs e )
{
if (e.KeyCode == Keys.C)
{
}
}
}
All help would greatly be appreciated.
Thanks

If this is in the scope of your application only, I would continue by making a hash map of keys to their binding. (KeyCode => Your-Binding)
If you want an integer value like in your example, you'll have a map like:
Dictionary<KeyCode,Integer> keyMap = new Dictionary<KeyCode,Integer>();
void Form1_KeyDown( object sender, KeyEventArgs e )
{
if(keyMap.ContainsKey(e.KeyCode) {
int boundValue = keyMap[e.KeyCode];
// continue with what you want to do here
}
}

Related

How do you keyboard focus on a specific item?

I am making a game where I need a constant keyboard listener (to navigate through the game). I tried getting the keyboard focus to one place and let it stay there using a seperate thread in a while true loop. This seems to crash my program.
Question:
Is there a method to get my keyboard focused on one element so I can grab my key input from there?
What can I use?:
something that works without throwing exceptions
something I can use in combination with other text input
something that doesn't take hours to compile
something that is easy to build another program (im not super good at c#)
What have I tried?
public MainWindow()
{
InitializeComponent();
Thread keyboardfocus = new Thread(GetFocus);
keyboardfocus.Start();
}
private void GetFocus()
{
while (true)
{
Keyboard.Focus(KeyboardButton);
}
}
private void KeyboardButton_OnKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Z)
{
map.PosUp -= 1;
MainCanvas.Background = Brushes.Aqua;
}
else if (e.Key == Key.S)
{
map.PosUp += 1;
MainCanvas.Background = Brushes.Black;
}
}
Thanks
Add event handler for Window.Loaded and set there a focus to the desired control:
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Keyboard.Focus(KeyboardButton);
}
Add event handler for the UIElement.LostKeyboardFocus in your case KeyboardButton and just set the keybord focus again to the KeyboardButton:
private void KeyboardButton_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
Keyboard.Focus(KeyboardButton);
}

C#_ Making buttons be pressed by either mouse or keyboard

Ok, so in my program I tried making buttons and assigning different methods for each button pressed. But I came into a problem where I also want the user to use his keyboard and assign buttons pressed on keyboard into same buttons on screen. Yet firstly, I tried if button is pressed by mouse or keyboard yet the method doesn't allow KeyEvents in 'EventArgs' (which is fine by me), so I created different method and made a boolean variable so that if in that separate method the key is pressed, make that variable true and in that main method if that is true then perform the code, yet the program ignores that keyboard variable and I have no idea why.
Then I tried making a different class as I thought maybe that would help. Now I can call that class and method inside it but not pass a parameter as it says it's a method so it can't do anything else but only be called.
If you're curious, here's the code below...
___
// the button '1' variable
bool pressOne = false;
___
// method for if that button is pressed
private void AnyNumberClick(object sender, EventArgs e)
{
Button btnSender = (Button)sender;
if (btnSender == btn_Num1 || pressOne)
{
// if button is pressed by either, perform code
}
}
___
// method for detecting which key is pressed for certain bool variable into button's method
public void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.D1)
{
pressOne = true;
}
else
{
pressOne = false;
}
___
// Call another class inside 'From1_KeyDown' method
Class1 newclass = new Class1();
newclass.buttonused();
NumResult.Text = newclass.buttonused.num();
The one with class I don't know how to start it. I don't even know if new class will help me there or not. I did the research but didn't find the answer. I appreciate any help from this.
Try it this way. I've setup a Dictionary<Keys, Button> to represent the relationship between a Key and a Button. Then I've overridden ProcessCmdKey() to trap key presses. If the key pressed exists in our lookup, then we click it with .PerformClick():
public partial class Form1 : Form
{
private Dictionary<Keys, Button> btnLookups = new Dictionary<Keys, Button>();
public Form1()
{
InitializeComponent();
// make your key -> button assignments in here
btnLookups.Add(Keys.F1, button1);
btnLookups.Add(Keys.F2, button2);
btnLookups.Add(Keys.F3, button3);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Button btn;
if (btnLookups.TryGetValue(keyData, out btn))
{
btn.PerformClick();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("button1");
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("button2");
}
private void button3_Click(object sender, EventArgs e)
{
MessageBox.Show("button3");
}
}
You need an event handler to tie to your method "AnyNumberClick". This is done in the Designer.cs portion of your form. Create a character array char[] and create a function within a button pressed event method, and then compare the button pressed against the set of characters in your array.
private void txt_box_keypress(object sender, KeyPressEventArgs e)
{
char[] SomeArray = {'a','b','c', etc};
int LengthOfArray = SomeArray.Length;
for (int x = 0; x < LengthOfArray; x++)
{
if (txt_box.Text.Contains(SomeArray[x]))
{
'Your method event here'
}
}
}

Perform action while key is pressed

In my program I would need that an action is perfomed while a key is pressed. I have already searched but the solutions either were not for c#, neither for forms or I couldnt understand them.
Is there a proper and easy solution to this?
EDIT: I am using WinForms and I want that while the form is focussed and a key is pressed an action is repeatedly performed.
First off, you need to provide a bit more information and if possible some code you already tried. But nevertheless I'll try. The concept is relatively easy, you add a timer to your form, you add key_DOWN and key_UP events (not key pressed). You make a bool that resembles if key is currently pressed, you change its value to true on keydown and false on keyup. It will be true while you hold the key.
bool keyHold = false;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (keyHold)
{
//Do stuff
}
}
private void Key_up(object sender, KeyEventArgs e)
{
Key key = (Key) sender;
if (key == Key.A) //Specify your key here !
{
keyHold = false;
}
}
private void Key_down(object sender, KeyEventArgs e)
{
Key key = (Key)sender;
if (key == Key.A) //Specify your key here !
{
keyHold = true;
}
}
**If you're trying to make a simple game on forms and you're struggling with the input delay windows has (press and hold a key, it will come up once, wait and then spam the key) This solution works for that (no pause after the initial press).
You can try this.
In the Key down event you set the bool 'buttonIsDown' to TRUE and start the method 'DoIt' in an Separate Thread.
The code in the While loop inside the 'DoIt' method runs as long the bool 'buttonIsDown' is true and the Form is on Focus.
It stops when the Key Up event is fired or the Form loose the focus.
There you can see the 'buttonIsDown' is set to false so that the While loop stops.
//Your Button Status
bool buttonIsDown = false;
//Set Button Status to down
private void button2_KeyDown(object sender, KeyEventArgs e)
{
Key key = sender as Key;
if (key == Key.A)
buttonIsDown = true;
//Starts your code in an Separate thread.
System.Threading.ThreadPool.QueueUserWorkItem(DoIt);
}
//Set Button Status to up
private void button2_KeyUp(object sender, KeyEventArgs e)
{
Key key = sender as Key;
if (key == Key.A)
buttonIsDown = false;
}
//Method who do your code until button is up
private void DoIt(object dummy)
{
While(buttonIsDown && this.Focused)
{
//Do your code
}
}

How can I move image with the KeyBoard using 2 keys?

I have a problem that I'm struggling with..
I want to move an image using my keyboard to the left, right, up or down and in a diagonal way.
I searched the web and found, that to use 2 diffrent keys I need to remember the previous key, so for that I'm using a bool dictionary.
in my main Form class this is how the KeyDown event looks like:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
baseCar.carAccelerate(e.KeyCode.ToString().ToLower());
carBox.Refresh(); //carbox is a picturebox in my form that store the image I want to move.
}
My KeyUp event:
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
baseCar.carBreak(e.KeyCode.ToString().ToLower());
}
My Paint event:
private void carBox_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(Car, baseCar.CharPosX, baseCar.CharPosY); // Car is just an image
}
And my baseCar class:
private Dictionary KeysD = new Dictionary();
// there is a method to set the W|A|S|D Keys, like: KeysD.Add("w",false)
public void carAccelerate(string moveDir)
{
KeysD[moveDir] = true;
moveBeta();
}
public void moveBeta()
{
if (KeysD["w"])
{
this.CharPosY -= this.carMoveYSpeed;
}
if (KeysD["s"])
{
CharPosY += carMoveYSpeed;
}
if (KeysD["a"])
{
CharPosX -= carMoveXSpeed;
}
if (KeysD["d"])
{
CharPosX += carMoveXSpeed;
}
}
public void carBreak(string str)
{
KeysD[str] = false;
}
Anyway it works, but my problem is that I can't get back to the first pressed key for example:
I pressed W to move up and then the D key to go diagonal, how ever when I release the D key it wont go Up again because the KeyDown event is "dead" and wont call the carAccelerate() method again..
and I can't figure out how to fix it..
Can any one help me please?
Maybe there is a better way to handle the keys? im open to any ideas!
And I hope you can understand it, my english isnt the best :S
Store all keystates and don't animate on keypress, but for example using a timer.
Then:
KeyDown(key)
{
KeyState[key] = true;
}
KeyUp(key)
{
KeyState[key] = false;
}
Timer_Tick()
{
Animate();
}
Animate()
{
if (KeyState["W"])
{
// Accelerate
}
if (KeyState["S"])
{
// Decelerate
}
}
Then in the KeyDown method you can check for conflicting keys (what if accelerate + decelerate are pressed at the same time, and so on).

Press Enter to move to next control

I have a few TextBox on the WinForm. I would like the focus to move to the next control when Enter key is pressed? Whenever a textbox gains control, it will also select the text, so that any editing will replace the current one.
What is the best way to do this?
Tab as Enter: create a user control which inherits textbox, override the KeyPress method. If the user presses enter you can either call SendKeys.Send("{TAB}") or System.Windows.Forms.Control.SelectNextControl(). Note you can achieve the same using the KeyPress event.
Focus Entire text: Again, via override or events, target the GotFocus event and then call TextBox.Select method.
A couple of code examples in C# using SelectNextControl.
The first moves to the next control when ENTER is pressed.
private void Control_KeyUp( object sender, KeyEventArgs e )
{
if( (e.KeyCode == Keys.Enter) || (e.KeyCode == Keys.Return) )
{
this.SelectNextControl( (Control)sender, true, true, true, true );
}
}
The second uses the UP and DOWN arrows to move through the controls.
private void Control_KeyUp( object sender, KeyEventArgs e )
{
if( e.KeyCode == Keys.Up )
{
this.SelectNextControl( (Control)sender, false, true, true, true );
}
else if( e.KeyCode == Keys.Down )
{
this.SelectNextControl( (Control)sender, true, true, true, true );
}
}
See MSDN SelectNextControl Method
In a KeyPress event, if the user pressed Enter, call
SendKeys.Send("{TAB}")
Nicest way to implement automatically selecting the text on receiving focus is to create a subclass of TextBox in your project with the following override:
Protected Overrides Sub OnGotFocus(ByVal e As System.EventArgs)
SelectionStart = 0
SelectionLength = Text.Length
MyBase.OnGotFocus(e)
End Sub
Then use this custom TextBox in place of the WinForms standard TextBox on all your Forms.
This may help:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
//
// Detect the KeyEventArg's key enumerated constant.
//
if (e.KeyCode == Keys.Enter)
{
MessageBox.Show("You pressed enter! Good job!");
}
}
You can put a KeyPress handler on your TextBoxes, and see which key was used.
To handle the text selection, put a handler on the GotFocus event.
You may also want to consider how to (or if you need to) handle multi-line TextBoxes.
private void txt_invoice_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
txt_date.Focus();
}
private void txt_date_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
txt_patientname.Focus();
}
}
You could also write your own Control for this, in case you want to use this more often.
Assuming you have multiple TextBoxes in a Grid, it would look something like this:
public class AdvanceOnEnterTextBox : UserControl
{
TextBox _TextBox;
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(String), typeof(AdvanceOnEnterTextBox), null);
public static readonly DependencyProperty InputScopeProperty = DependencyProperty.Register("InputScope", typeof(InputScope), typeof(AdvanceOnEnterTextBox), null);
public AdvanceOnEnterTextBox()
{
_TextBox = new TextBox();
_TextBox.KeyDown += customKeyDown;
Content = _TextBox;
}
/// <summary>
/// Text for the TextBox
/// </summary>
public String Text
{
get { return _TextBox.Text; }
set { _TextBox.Text = value; }
}
/// <summary>
/// Inputscope for the Custom Textbox
/// </summary>
public InputScope InputScope
{
get { return _TextBox.InputScope; }
set { _TextBox.InputScope = value; }
}
void customKeyDown(object sender, KeyEventArgs e)
{
if (!e.Key.Equals(Key.Enter)) return;
var element = ((TextBox)sender).Parent as AdvanceOnEnterTextBox;
if (element != null)
{
int currentElementPosition = ((Grid)element.Parent).Children.IndexOf(element);
try
{
// Jump to the next AdvanceOnEnterTextBox (assuming, that Labels are inbetween).
((AdvanceOnEnterTextBox)((Grid)element.Parent).Children.ElementAt(currentElementPosition + 2)).Focus();
}
catch (Exception)
{
// Close Keypad if this was the last AdvanceOnEnterTextBox
((AdvanceOnEnterTextBox)((Grid)element.Parent).Children.ElementAt(currentElementPosition)).IsEnabled = false;
((AdvanceOnEnterTextBox)((Grid)element.Parent).Children.ElementAt(currentElementPosition)).IsEnabled = true;
}
}
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Enter))
{
SendKeys.Send("{TAB}");
}
return base.ProcessCmdKey(ref msg, keyData);
}
goto the design form and View-> tab(as like picture shows) Order then you ordered all the control[That's it]
Try to use:
SendKeys.Send("{TAB}")

Categories