I have a Form1_KeyDown event for form1, but while I am typing some text in the Textbox on the Form, the event gets triggered.
How can I stop that event when I am typing inside the textboxes on the form.
There are two ways:
Set form's KeyPreview to false. Which is the default, so you must have explicitly changed it, presumably for a reason. Otherwise the controls of on the form always get the keyboard events first.
Add an active control check in Form1_KeyDown, like this:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (this.ActiveControl == textBox1) return;
var k = e.KeyCode;
}
Related
I'm making a settings form, where user can assign custom hotkeys for the application. There's a TextBox, and by clicking it with mouse, it focuses and waits for one keypress and then defocuses (by focusing another label):
private void txtKey_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
}
private void txtKey_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
TextBox textBox = (TextBox)sender;
textBox.Text = e.KeyCode.ToString();
label1.Focus();
}
Is there a way to defocus focused TextBox (and cancel the key assinging process), by either clicking it again with mouse, or by clicking the GroupBox around it? I can't figure out how to check if TextBox was already focused when clicked (because when clicked, it gets focused before I can test if it's focused). Of course I can add a button "Cancel" next to the TextBox, but that's not what I want.
There is no Click-event for GroupBox, so I can't defocus TextBox by clicking GroupBox around it. Or can I somehow?
You can set/remove the Focus with
Keyboard.Focus = null;
You can also register to the following event:
public event MouseButtonEventHandler PreviewMouseLeftButtonDown
This event fires every time you click on the TextBox, thus you can set the Focus there if you want to.
For Winforms there is a way as well. I'm not proficient in it, but here would be a way:
Make a textBox (e.g. named textBoxFocus) that lies outside your window. Size it 1, 1 and move it to -10,-10 for example. Then you can register to the Click event and write
textBoxFocus.Focus();
It's a bit of a roundabout way, but should achieve what you want.
Thanks to private_meta for getting me to right direction (in comments)! I set the flag with click event, and before setting the flag, testing if flag is set. So first click does not find the flag, but second will. And flag is cleared within textbox Enter-event (which fires before Click-event). Now every other click focuses and every other defocuses textbox, as I wanted.
private void txtKey_Enter(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
textBox.Tag = null;
}
private void txtKey_Click(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
if (textBox.Tag != null) label1.Focus();
textBox.Tag = "clicked";
}
One of the simple way is that, you may use a bool flag here.
Algorithm:
By default, the bool value is 0;
If(Textbox Selected && flag = 0)
Do your task; and flag = 1;
I hope I could satisfy your query and you can follow this algorithm.
Im trying to do like that: If I press the key "P" a messagebox will open in the screen.But I need to do it without a textbox or other tool, I want to do that direct in the form.
I tried:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.P)
{ MessageBox.Show("Key P pressed"); }
}
Try with the KeyPress Event of the form. It just works fine.
Assuming this is Winforms, on the form you're trying to catch the event on, make sure to set
Form1.KeyPreview = true;
KeyPreview ensures that keyboard events anywhere on the particular form (such as to a textbox with focus) will still count as a keyboard event for the form itself.
I've read quite some articles now about key press events but I can't figure out how to get them. I know that only the current control with keyboard focus gets the press events. But how can i ensure that my user control has it?
Tried this without luck:
public partial class Editor : UserControl
this.SetStyle(ControlStyles.Selectable, true);
this.TabStop = true;
...
//take focus on click
protected override void OnMouseDown(MouseEventArgs e)
{
this.Focus();
base.OnMouseDown(e);
}
...
protected override bool IsInputKey(Keys keyData)
{
return true;
}
And also this:
//register global keyboard event handlers
private void Editor_ParentChanged(object sender, EventArgs e)
{
if (TopLevelControl is Form)
{
(TopLevelControl as Form).KeyPreview = true;
TopLevelControl.KeyDown += FCanvas_KeyDown;
TopLevelControl.KeyUp += FCanvas_KeyUp;
TopLevelControl.KeyPress += FCanvas_KeyPress;
}
}
The latter gave me the key down and up events, but still no key press. Is there any other method i can use to just get every down/up/press events when my control inherits from UserControl?
Edit:
As there was a comment linking another SO question: It's important that I also get the KeyPress event, since it sends the correct character on every keyboard no matter which language. This is important for text writing. If you only get the individual keys you have to process them into the correct character on your own. But maybe there is a convenience method to transform the pressed keys into a localized character?
Set your parent form's (contains the usercontrol) KeyPreview property to true
Add a new KeyPress event to your parent form
Set the parent form keypress event to forward the event to your usercontrol:
private void parentForm_KeyPress(object sender, KeyPressEventArgs e)
{
// Forward the sender and arguments to your usercontrol's method
this.yourUserControl.yourUserControl_KeyPress(sender, e);
}
Replace the yourUserControl1_KeyPress method with your own method, which you want to run each time the user presses a button (the button is pressed down and then released).
You can also create a new KeyPress handler to your usercontrol, and forward the sender and KeyPressEventArgs objects there, as in this example.
Can you attach to form event.
Private Sub MyControl_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim f = Me.FindForm
If Not f.KeyPreview Then Throw New Exception("Form requires has Keypreview enabled")
AddHandler f.KeyUp, Sub(sender2 As Object, e2 As KeyEventArgs)
End Sub
End Sub
I have this code:
private void button5_Click(object sender, EventArgs e)
{
Magnifier20070401.MagnifierForm mf = new Magnifier20070401.MagnifierForm();
mf.Show();
}
It shows the target form correctly. But instead of using a button click, I want to use Ctrl+M to show this form. If the users types Ctrl+M again, I want to close the the form.
How can I do this?
Edit:
This is what i did wich is working :
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode.ToString() == "M")
{
Magnifier20070401.MagnifierForm mf = new Magnifier20070401.MagnifierForm();
mf.Show();
}
}
In the constructor of Form1 i added:
this.KeyPreview = true;
So now when i click on Ctrl+M i see the new Form.
What i need now is how to make that if i click again on Ctrl+M it will close the new Form.
Maybe using a flag ?
Edit:
This is what i did now:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode.ToString() == "M")
{
if (mf == null)
{
mf = new Magnifier20070401.MagnifierForm();
mf.Show();
}
else
{
mf.Close();
this.Invalidate();
}
}
}
But even doing this.Invalidate(); i don't see the new Form closed.
But if im using put a breakpoint on the mf.Close(); and step into(F11) i see it close when making continue.
Why it dosen't close without using a breakpoint ?
You can add onKeyPress or onKeyDown
and check if Ctrl+M were pressed
private void OnKeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
if (((Control.ModifierKeys & Keys.Control) == Keys.Control)
&& (e.KeyChar == 'M'|| e.KeyChar == 'm'))
{
mf.Show();
}
You would use the InputBindings object. I think in your case, probably best to put that at the Window level (Window.InputBindings). More information here:
http://msdn.microsoft.com/en-us/library/system.windows.input.inputbinding.aspx
You can solve this in 2 ways.
If you are using a GUI interface, add a MenuItem control on your Menu, and put the Shortcut property to Ctrl+M then double click the MenuItem to edit the code, then call your launchMagnifier() function. If you do NOT want your menu to show, just set the visible properties to false. This keeps the menu hidden if you do not want it, yet still holds the functionality.
If you do not want the MenuItem, you can catch keys that are pressed in your form. So in your frmMain.cs form, add an event to capture keys, then when Ctrl+M is pressed, invoke launchMagnifier()
A few ways to do that.
On your form set the KeyPreview Property to true
Then add an OnKeyPress or OnKeyDown event handler to the form.
In that test for Ctrl-M and show / destroy the form and set handled (e.Handled) to true.
Any other keypress will be passed on to the currently focused control as it hasn't been handled.
If I do not create an "Edit->Copy" menu item and assign it the shortcut keys "CTRL+C", then I can select a control (RichTextBox, DataGridView, etc..) and hit "CTRL+C" and the control itself will handle the copy. I can copy text out, and paste it into notepad, etc..
Now throughout my whole form, I have a lot of controls. But I have a custom control that I want to make clear that I handle Copy functionality for. So I added the ShortcutKey CTRL+C to Edit->Copy, and by default it is set to Enabled.
Now, I have to implement an event handler for the 'click' event on that menu item. If I explicitly put in code to handle the copy, then it works:
public void menuEditCopy_Click(object sender, EventArgs e)
{
myCustomControl.Copy();
}
However, now Copy does not work on any other type of control. My first inclination was to find out the type of control that has focus, and implement a limited set of copy code for each of them:
public void menuEditCopy_Click(object sender, EventArgs e)
{
if (this.ActiveControl is MyCustomControl)
{
((MyCustomControl)this.ActiveControl).Copy();
}
else if (this.ActiveControl is RichTextBox)
{
((RichTextBox)this.ActiveControl).Copy();
}
}
etc...
However, my controls are added to a SplitContainer, and debugging shows that this.ActiveControl is set to the splitcontainer instance, not the control, even though I know that control is selected.
So my last thought is to literally check if every control has focus:
public void menuEditCopy_Click(object sender, EventArgs e)
{
if (myCustomControl.Focused)
{
myCustomControl.Copy();
}
else if (richTextBox1.Focused)
{
richTextBox1.Copy();
}
}
I would like to avoid this if possible, it is a lot of controls, and if I add a new control, I would need to update it. Is there a better way of doing this?
Thanks
A SplitContainer implements ContainerControl, so you could check for either one and look for it's ActiveControl instead. ContainerControl is the base class, so I would go for that - you might catch another type of container as well:
private void DoCopy(Control control)
{
if(control is ContainerControl)
DoCopy(control.SelectedControl);
else if(control is MyCustomControl)
((MyCustomControl)control).Copy();
else if(control is RichTextBox)
((RichTextBox)control).Copy();
else
throw new NotSupportedException("The selected control can't copy!");
}
void menuEditCopy_Click(object sender, EventArgs e)
{
DoCopy(this.ActiveControl);
}
You could try settting the KeyPreview property of your form to true. Then you could set up a handler for the form's KeyDown event which would look like the following:
private void Form_KeyDown(object sender, KeyEventArgs e)
{
if(e.Modifiers == Keys.Control && e.KeyCode == Keys.C)
{
if (ActiveControl.GetType() == typeof(MyCustomControl))
{
((MyCustomControl)ActiveControl).Copy();
e.Handled = true;
}
}
}
Here you are specifying that you have handled the Ctrl-C event by setting the event args Handled property to true. Else, if you leave it as false, the Ctrl-C key press will be handled as per usual by each individual control.
Because we have set the KeyPreview to true the form's handler gets to see each key press before any other control that it contains and can decide to deal with the key press itself or else allow it to be handled in the same way as if the form had never previewed it.
I think as well it would be necessary to remove the short-cut key from your menu item (although you could still manually put the text "Ctrl+C" next to your menu item name) for this to work, otherwise your menu item will hijack the key stroke.