I want to handle crtl+click event in WPF XAML code behind. I registered KeyDown event and MouseDown event, but I am not able to register for them together. What is that I am missing.
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.LeftCtrl))
{
//do something
}
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 1)
{
//do something
}
}
Thanks,
RDV
Don't bother tracking Key Up/Down events--they're not reliable (e.g., user may switch windows between pressing and releasing). Just check Keyboard.Modifiers when you process the click.
If you only want to handle Ctrl+Click and not, for example, Ctrl+Shift+Click, then check Modifiers for an exact match:
if (e.ClickCount == 1 && Keyboard.Modifiers == ModifierKeys.Control) {
}
Otherwise, do a selective bitwise match:
if (e.ClickCount == 1 && (Keyboard.Modifiers & ModifierKeys.Control) != 0) {
}
Keyboard.Modifiers should generally be consistent: it won't reflect the release of the control key until after you process the mouse event, because all input events are processed in FIFO order.
Be sure to read up on bubbling versus tunneling events (e.g., MouseDown vs. PreviewMouseDown), and how events stop routing once they are marked as Handled.
As an alternative, you may be able to use a simple MouseGesture with a MouseAction of LeftClick and Modifiers of Control. It really depends on what your UI looks like, and whether you want a chance at handling the event before any descendant controls. Using a mouse gesture should work in (mostly) the same scenarios as handling the bubbling MouseDown event. But if you need to rely on tunneling events like PreviewMouseDown, then a gesture wouldn't work.
Do something like this, with a flag:
bool _isControlPressed = false;
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.LeftCtrl))
{
_isControlPressed = true;
}
}
private void Window_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.LeftCtrl))
{
_isControlPressed = false;
}
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 1 && _isControlPressed)
{
//do something
}
}
The _isControlPressed flag is set/unset in the key down/key up events. You can then use this flag in other methods to determine the key state.
Related
I’m using a PasswordBox control in wpf.
I want to block space in the control, but i can’t find the way.
I tried to use a KeyDown event but the event isn’t working.
What is the best way to block space in the PasswordBox?
For WPF you should using PreviewKeyDown Based on docs occurs before the KeyDown event When a key is pressed while focus is on this control.
XAML:
<PasswordBox x:name="txtPasscode" PreviewKeyDown="txtPasscode_PreviewKeyDown"/>
and in behind :
private void txtPasscode_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space && txtPasscode.IsFocused == true)
{
e.Handled = true;
}
}
Also in C# native try this :
private void txtPasscode_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == ' ') e.Handled = true;
}
The KeyDown event you're handling actually fires after the character added to the passwordbox. You can block it by handling PreviewKeyDown this way(KeyDown won't fire anymore if user pressed space):
private void passwordbox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
e.Handled = true;
}
}
If you need to block an event you're going to use the event beginning with "Preview"(read more here).
I need an application that can detect the keypress of F13-F24. I tried making a form and setting keydown and Keypress events and printing in a messagebox the key pressed but when i press F13-F24, i don't get a messagebox
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show(e.KeyCode.ToString());
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
MessageBox.Show(e.KeyChar.ToString());
}
This didn't seem to work. How can I do this?
You can capture this using System.Windows.Forms.KeyEventHandler.
The KeyEventHandler will provide a KeyEventArgs object that includes a KeyCode property. KeyCode is a System.Windows.Forms.Keys enumeration and supports F1-F24.
private void KeyDownHandler(object sender, System.Windows.Forms.KeyEventArgs e) {
if (e.KeyCode == Keys.F13) {
//F13
} else if (e.KeyCode == Keys.F14) {
//F14
} else if (e.KeyCode == Keys.F15) {
//F15
}
// etc
}
If you don't have a keyboard capable of sending higher F-keys, the F13-F24 keys are the equivilent of SHIFT-F1-SHIFT-F12. You can capture this sequence using the KeyCode and Modifiers (Modifiers == Keys.Shift) properties together.
Windows 10 doesn't recognize the higher Function keys 13-24. You can test this by turning on the Windows Narrator functionality, and then press Shift -F1. The narrator just says "Shift F1", not "F13"
So, instead I recommend that you just detect Shift -F1 to Shift -F12 instead.
private void Form1_PreviewKeyDown(object sender, KeyPressEventArgs e)
{
if(e.KeyCode == Keys.F1 && e.Modifiers == Keys.Shift)
{
MessageBox.Show("Shift-F1 pressed");
}
}
As MstfAsan commented, you need to use the PreviewKeyDown eventhandler and set the form's KeyPreview property to True for this to work
private void MeretOK_Click(object sender, EventArgs e)
{
//code
}
private void MeretTB_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode==Keys.Enter)
{
MeretOK_Click();
}
}
How can I start an event with a hotkey?
(I know I can just copy the code there but that is ugly)
If I just copy the code and run it I hear a beep. Why?
First, you have to allow your form to handle key events globally (set the form KeyPreview property to true) and to mark your event as internally handled. Second, if the purpose of this code is to simulate the mouse click on a specific control (programmatic click), for example a button, there is an easier way to accomplish it:
private void MeretTB_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
myButton.PerformClick();
}
}
I have a disabled control. I still want the key down and key up events to get fired off, because I would like to be aware of a certain key.
When I tested this out, it seems like none of the control's events get fired. Any ideas on how to get around this?
Lack of interaction is basic idea of disabling control, it is working as intended.
You might use KeyPreview property of Form and then launch event handlers of your disabled control from Form events.
As usually, there is n+1 ways to achieve what you seek for. So I will present only some of them.
1 - Manipulate Focus. Although easy to implement, it is also volatile as user can manipulate focus as well.
private void button_KeyDown(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Add(helpBox);
((Control)sender).Focus(); // Set focus back to control so its KeyUp will be called
}
private void button_KeyUp(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Remove(helpBox);
}
2 - Multiple calls to same event handler. Yes, it is possible. A bit more complicated and might depend on helpBox control class and/or its events. Possible issues may include multiply fired up event handler, however presented code is safe to use even if such situation will occur.
private void button_KeyDown(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Add(helpBox);
helpBox.KeyUp += button_KeyUp; //This will add KeyUp of our hosting button to hosted control, which means that said KeyUp handler can be raised by both helpBox and button
}
private void button_KeyUp(object sender, KeyEventArgs e)
{
((Control)sender).Controls.Remove(helpBox);
helpBox.KeyUp -= button1_KeyUp; // to avoid unnecessary calls event handler can be easily "subtracted" from helpBox
}
3 - Master control by Form itself by use of KeyPreview set to true, shows controls with "help_" as helpBoxes on controls named .
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
foreach (Control c in this.Controls)
{
string hName = "help_" + c.Name;
Control[] help = this.Controls.Find(hName, true);
if (help.Length>0)
{
c.Controls.Add(help[0]);
}
}
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
foreach (Control c in this.Controls)
{
string hName = "help_" + c.Name;
Control[] help = c.Controls.Find(hName, true);
if (help.Length > 0)
{
c.Controls.Remove(help[0]);
}
}
}
}
Note: Control on-screen position depends on its parent position (relative to top-left corner of parent), in other words, by changing parent of control (which happens during Controls.Add) control will change its position.
4 - Draw it by yourself! Manipulating controls is not always best solution, instead you might want to just draw something on control.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
button1.Tag = true;
button1.Update();
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
button1.Tag = false;
button1.Update();
}
// there is no reason to re-draw it constantly, Paint event will be fired when needed
private void button1_Paint(object sender, PaintEventArgs e)
{
// remember that all Tag's start as null
if (((Control)sender).Tag != null && (bool)((Control)sender).Tag == true)
{
// and when needed just paint on control drawing area (also known as Canvas)
e.Graphics.FillRectangle(Brushes.Red, 0, 0, 100, 100);
e.Graphics.DrawString("Foo!", ((Control)sender).Font, Brushes.Beige, new PointF(5, 5));
}
}
Note: Every Control have Tag property, due to it being of object type you can store in it anything you want. Which makes it universal custom property. In case you wonder about meaning of this property: it have no meaning, it is made to be user-defined.
I have added a keyPress event on a ListView. With a breakpoint on my event, I can see that most of the keys trigger the event. However, a few among which, the one I'm interested in (delete), just won't trigger my event.
Is that weird ? And no, there's no broken keys on my keyboard :D
private void listView1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Delete)
{
ListView target = (ListView)sender;
if (target.SelectedIndices != null && target.SelectedIndices.Count > 0)
{
string ric = target.SelectedItems[0].SubItems[0].Text;
//target.Items.RemoveAt(target.SelectedIndices[0]);
ListModels.getInstance().getModel("Vols").removeRic(ric);
}
}
}
The reason for this is that the KeyPress event sends a character to the control based upon the character-key you press. However, as you'd expect, the delete key does not represent a character and is thus a non-character key.
Therefore using the KeyPress event will do nothing as you have noticed. You should use the KeyDown or KeyUp Events, either of which will work absolutely fine. The nuance being whether you want your event to fire upon pressing, or letting go of a key.
You'll want to use the KeyDown event for this.
In KeyDown use the condition as follows,
if (e.KeyCode == Keys.Delete)
{
// Your Logic....
}
Use keyDown instead; keyPress is something like a full keyDown + keyUp
The problem is that if you set EditMode property to EditOnEnter it won't fire. If you use EditOnKeyStrokeOfF2 it will fire the event
If you are looking for a solution where the user should only be able to choose from the defined items, then I believe you can do it with this:
private void DropDownRank_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
}
See this code:
private void Form1_Load(object sender, EventArgs e)
{
listView1.KeyUp += new KeyEventHandler(ListView_KeyUp);
}
/// <summary>鍵盤觸發 ListView 清單</summary>
private void ListView_KeyUp(object sender, KeyEventArgs e)
{
ListView ListViewControl = sender as ListView;
if (e.KeyCode == Keys.Delete)
{
foreach (ListViewItem eachItem in ListViewControl.SelectedItems)
{
ListViewControl.Items.Remove(eachItem);
}
}
}
I tried all the stuff mentioned above but nothing worked for me, so im posting what i actually did and worked, in the hopes of helping others with the same problem as me:
Add an event handler in the constructor:
public partial class Test
{
public Test()
{
this.RemoveHandler(KeyDownEvent, new KeyEventHandler(Test_KeyDown));
// im not sure if the above line is needed (or if the GC takes care of it
// anyway) , im adding it just to be safe
this.AddHandler(KeyDownEvent, new KeyEventHandler(Test_KeyDown), true);
InitializeComponent();
}
//....
private void Test_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete)
{
//your logic
}
}
}