c# pass keydown from form to usercontrol - c#

I have a calculator usercontrol, the usercontrol is added to a panel in my form:
On my main Form I have:
private void frmPOS_KeyDown(object sender, KeyEventArgs e)
{
// here I want to pass the keydown captured to my calculator
// usercontrol so the KeyDown event is fired in my usercontrol
}
In my Calculator.cs I have:
private void Calculator_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.NumPad0:
// one
lblResult.Text = "0";
break;
case Keys.NumPad1:
// one
lblResult.Text = "1";
break;
case Keys.NumPad2:
// two
lblResult.Text = "2";
break;
// .. etc
case Keys.Add:
// Plus
break;
default:
// Avoid setting e.Handled to
return;
}
e.Handled = true;
}
Any clue?

One way I have done this is by creating an event on the user control and raise it when the actual event happens. So, in the user control I would do something like...
public partial class Calculator : UserControl
{
//create an event
public event EventHandler<KeyPressEventArgs> OnKeyPressed;
public Calculator()
{
InitializeComponent();
}
private void Calculator_KeyPress(object sender, KeyPressEventArgs e)
{
//raise the event when the key press happens and someone is listening
if (OnKeyPressed != null)
{
OnKeyPressed(sender, e);
}
}
}
and then on the Main form you would subscribe to the event and handle it..
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//subscribe to the event we create on the user control
calculator1.OnKeyPressed += new EventHandler<KeyPressEventArgs>(MyKeyPressHandlerInMainForm);
}
private void MyKeyPressHandlerInMainForm(object sender, KeyPressEventArgs e)
{
//Handle the event. Here you would write your logic.
//Since you have keypressEventArgs coming in as a parameter you would be able to
//do determine what key was pressed and all that.
}
}
enter code here

You can move your switch block to a new public method in the control, eg.:
public void HandleKeyEvent(KeyEventArgs e) { ... }
This method can be invoked from your form (and your existing control event handler if you need to keep it).
As a side note, if you set the form's KeyPreview-property to true you won't get problems with a focused control incorrectly getting the event. See MSDN for more information about this property.

Related

Handling some keys while textbox is focused

So, apparently I had some problem when handling keys such as F10 or F11.
I want to move the focus from current textbox into another textbox, but not in one particular textbox. So, I wrote some code to handle key:
private void checkKeys(KeyEventArgs e)
{
if (e.KeyCode == Keys.F10)
{
buyerName.Focus();
}
else if (e.KeyCode == Keys.F11)
{
discount.Focus();
}
}
But, if I put this into individual textbox, which kinda hassle to me. Is there any method to listen key whether in global userControl or textbox?
Edit : here's my structure that I want to ask :
Form-
|-User Control
|-TextBox
Edit 2 : here's some image might help img
To use a global keyboard listener in Winforms, you just need to add a handler to KeyUp action for the main form itself:
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F10)
{
textBox1.Focus();
e.Handled = true; //To use F10, you need to set the handled state to true
} else if (e.KeyCode == Keys.F11)
{
textBox2.Focus();
}
}
Then make sure that the KeyPreview property on the main form is set to True.
The issue with the application freezing when pressing F10 is because it is waiting for another consecutive action. To bypass this simply set the Handled property on the keyevent to TRUE. This releases the unresolved event.
This is my entire form class, refactored to use a helper method as you are refering to. This works fine. But you have to make sure that the KeyPreview property on your form is True, unless your keypresses will not be matched to your event handlers.
namespace KeyTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
CheckKeys(e);
}
private void CheckKeys(KeyEventArgs e)
{
if (e.KeyCode == Keys.F10)
{
textBox1.Focus();
e.Handled = true;
}
else if (e.KeyCode == Keys.F11)
{
textBox2.Focus();
e.Handled = true;
}
}
}
}
Now in your comment you are mentioning a UserControl, if you want that, then you need to create an instance method on your UserControl class, and pass the event to that from your global keyboard event handler on your main form.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public void HandleKeys(KeyEventArgs e)
{
if (e.KeyCode == Keys.F10)
{
textBox1.Focus();
e.Handled = true;
}
else if (e.KeyCode == Keys.F11)
{
textBox2.Focus();
e.Handled = true;
}
}
}
Then on your main form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
CheckKeys(e);
}
private void CheckKeys(KeyEventArgs e)
{
uc1.HandleKeys(e); //Instance method on your user control.
}
}
This then works as intended.
As pointed out in one of the comments, a better way would be to override the ProcessCmdKey method on the Form base class. This would be done like so:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
userControl11.HandleKeys(keyData); // method on the userControl to handle the key code.
base.ProcessCmdKey(ref msg, keyData);
return true;
}
}
The handler on the UserControl stays more or less the same:
public void HandleKeys(Keys keys)
{
if (keys == Keys.F10)
{
nameTB.Focus();
} else if (keys == Keys.F11)
{
emailTB.Focus();
}
}
Whether this is a more correct way of doing it, I am unsure of. They certainly both accomplish the same result. The documentation shows the first method in for handling keyboard events at the form level here:
How to handle keyboard input
But states here that the ProcessCmdKey method is to provide additional handling of shortcuts and MDI accellerators.
ProcessCmdKey
I will leave that up to you to decide what is the best for your scenario. But keep it in to show how you would use it should you choose to.
You can hook up to the KeyUp event of your form.
That way, any key pressed while your form is focused will be send to you (if the control didn't handle the key).
Thanks to #Espen and #reza-aghaei for handling keys into main form. Unfortunately, I still didn't managed find a way to focus to designated textbox inside a UserControl. However, I make some dirty method which kinda crappy and un-efficient by searching child control from it's parent
//MainForm.cs
if(yourUserControl.Name)//Do some check for targeted userControl, if null can cause NullReferenceException
{
if (e.KeyCode == Keys.F10)
{
this.Controls.Find("textboxName", true).First().Focus();
e.Handled = true;
}
}

UWP key press event handled too late prevent keyboard focus action

I have an UWP app that controls my tv. I have some Buttons, Checkboxes etc. and keyboard controls/events. This combination causes problems. When check a checkbox and then press VirtualKey.Subtract the checkbox is unchecked and I don't want any changes through keyboard. The use of e.Handled doesn't seem to work.
How can I disable default Keyboard navigation behaviour or Keyboard Focus in a UWP App?
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
Window.Current.CoreWindow.KeyDown += KeyEventHandler;
Window.Current.CoreWindow.KeyUp += KeyEventHandlerDevNull;
}
private void KeyEventHandlerDevNull(CoreWindow sender, KeyEventArgs e)
{
e.Handled = true;
}
private async void KeyEventHandler(CoreWindow sender, KeyEventArgs e)
{
e.Handled = true; //gets unset in case of default
if (MainViewModel.ControlsEnabled)
{
switch (e.VirtualKey)
{
case VirtualKey.Left:
await ButtonPressLeft();
break;
case VirtualKey.Right:
await ButtonPressRight();
break;
default:
e.Handled = false;
break;
}
}
}
Sorry if this question might be a duplicate one but I think it's different for UWP (Universal Windows Platform).
You need to implement/use your custom checkbox and override the OnKeyDown Event to prevent changes to your checkbox.
public sealed partial class MyCheckBox : CheckBox
{
public MyCheckBox()
{
this.InitializeComponent();
}
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
e.Handled = true;
//your logic
}
}

a custom event for pressing the 'Enter key' in C#

I have a UserControl with some controls and a textbox on it, i want to do some procedures when the Enter key hits on that textbox, I have this code in the UserControl:
public event EventHandler TextBoxKeyPressed
{
add { textBox.KeyPressed+=value; }
remove { textBox.KeyPressed-=value; }
}
in my main form I have a lot of this control and for each one I should check for the key pressed and if it was Enter key then do the procedures.
Is there any way to create a custom event to check the key pressed in the UserControl and if it was Enter Key then fire that event?
Update: each custom control may have different procedures on KeyPresssd event
Sure, you can just add, say, an EnterPressed event and fire it when you detect that the Enter key was pressed:
public partial class UserControl1 : UserControl {
public event EventHandler EnterPressed;
public UserControl1() {
InitializeComponent();
textBox1.KeyDown += textBox1_KeyDown;
}
protected void OnEnterPressed(EventArgs e) {
var handler = this.EnterPressed;
if (handler != null) handler(this, e);
}
void textBox1_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Enter) {
OnEnterPressed(EventArgs.Empty);
e.Handled = e.SuppressKeyPress = true;
}
}
}
The event doesn't change, it would still be a normal key pressed event. You'd simply only perform the intended action therein if the key was the enter key. Something like this:
private void textBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Return)
{
// the enter key was pressed
}
}

What to pass to Method that Checks if Key is Pressed?

Okay so I created a method called KeyCheck(), that should check if a key is pressed (specifically the enter key) and if it is it will press button1.
Unfortunately when I call the method I am unsure what to pass along to it. I want it to know when the enter key is being pressed.
public partial class Form1 : Form
{
public void GameStart()
{
richTextBox1.WordWrap = true;
richTextBox1.SelectionAlignment = HorizontalAlignment.Center;
richTextBox1.Text = "Hello, Welcome to Grandar!";
}
public Form1()
{
InitializeComponent();
GameStart();
//What variable do I pass to KeyCheck Method?
KeyCheck();
}
private void KeyCheck(KeyPressEventArgs k)
{
if (k.KeyChar == (char)Keys.Enter)
{
button1.PerformClick();
}
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
}
Couple of things to note here:
a) Do you really want to be calling KeyCheck directly as your sample code suggests or should it be wired up as a handler on the form (where the info you're asking will be automatically provided - will require a change in signature to align with the standard handlers as you have in some of your other methods).
b) I don't think you'll be able to call the KeyCheck method like you're doing unless you hook up another event to capture the keypress and then pass it to this method, by newing up a new KeyPressEvent(...)
Therefore, to answer your question, I think you'll want something like (pseudo-code)
public Form1()
{
InitializeComponent();
GameStart();
// Wire up a handler for the KeyPress event
this.KeyPress += KeyCheck;
}
private void KeyCheck(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
button1.PerformClick();
}
}
Check out this page: https://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress(v=vs.110).aspx
You'll want something similar to your other methods, with the sender object and the event args.
if (e.KeyCode < Keys.Enter) {
//Your logic
}
subscribe to this:
this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.KeyPress_Method);
and the method to check the Enter key:
void KeyPress_Method(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13) // enter key
{
// your code
}
}

How to check from which button I called form in C#?

I have "formA" and 2 buttons on it (button1 and button2). What I want to do is:
When I click on button1 to call "formB" display text written in label1.
When I click button2 to call the same form ("formB") hide label1 and display label2.
The problem is that I don't know how to check what button is clicked on "formA".
Edit: Thanks very much folks for the quick answer. Problem is solved!
This is where events come in handy:
public class FormA
{
private void button1_Click(object sender, EventArgs e)
{
formB.Button1WasClicked();
}
private void button2_Click(object sender, EventArgs e)
{
formB.Button2WasClicked();
}
}
public class FormB
{
public void Button1WasClicked()
{
label2.Visible = false;
label1.Visible = true;
label1.Text = "Button 1 was clicked!";
}
public void Button2WasClicked()
{
label1.Visible = false;
label2.Visible = true;
label2.Text = "Button 2 was clicked!";
}
}
button1 and button2 have their own separate Click event handlers. This way we can differentiate the two when they are clicked.
If you have the same event handler for both buttons (as mentioned in one of the comments), you can identify them with the sender parameter using:
Object.ReferenceEquals(sender, button1);
or
Object.ReferenceEquals(sender, button2);
Then your code would look like this:
private void button_Click(object sender, EventArgs e)
{
if (Object.ReferenceEquals(sender, button1))
{
formB.Button1WasClicked();
}
else
{
formB.Button2WasClicked();
}
}
FormB can't find out, the buttons are a private implementation details of FormA. They might not even be a button, surely you are going to add a menu or a toolbar to FormA some day.
The workaround becomes much simpler if you stop thinking of "calling a form". You never call a form, you create an instance of it. And then you make it visible by calling its Show() method. Lots of things you can do in between those two steps.
Add a public method to FormB. For lack of a better name:
public void MakeLabel2Visible() {
this.label1.Visible = false;
this.label2.Visible = true;
}
Now it becomes simple. Implement button2's Click event handler like this:
private void button2_Click(object sender, EventArgs e) {
var frm = new FormB();
frm.MakeLabel2Visible();
frm.Show();
}
Adding another constructor to a form that lets you initialize it differently is another very common approach. These are just classes, standard programming techniques are appropriate.
Because you are using winforms you can do all this very easily due to the fact that you have a stateful environment.
Assuming a very basic set up with:
event handlers in the code behind of form a
a reference to an instance of form b in form a (or the button click creating such an instance)
a method to use in form b to pass it data
Your code will be something like this:
public partial class FormA : Form
{
private FormB formB;
public FormA()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (formB == null || formB.IsDisposed)
{
formB = new FormB();
}
formB.UpdateLabel("Button A");
formB.Show();
}
private void button2_Click(object sender, EventArgs e)
{
if (formB == null || formB.IsDisposed)
{
formB = new FormB();
}
formB.UpdateLabel("Button B");
formB.Show();
}
}
public partial class FormB : Form
{
public FormB()
{
InitializeComponent();
}
public void UpdateLabel(string message)
{
label1.Text = message;
}
}
Of course, there are lots of improvements to this - using events and alerts more intelligently and refactoring to remove duplication, but this is a basic example of the sort of things you can do.

Categories

Resources