简体   繁体   中英

How to handle shortcuts and keyboard events properly?

Got a problem with short cuts, any help/tips would be much appreciated! Goal: I need to be able to handle short cut keys, with and without modifiers in my app. So for instance i need to handle a key 'a' as well as 'CTR+a'. But I want to handle them only if no control handles these keys. For instance TextBox class takes most keys, including some commands like 'Ctrl+C' etc, so I don't want to intercept these events when TextBox will handle them.

I tried using Commands as well as attaching events to KeyUp to the Window, but, commands intercept keys before the TextBox gets a chance to view them, KeyDown bubbles to the Window level even if TextBox used the key! How can I get my window to get the keys that are NOT handled by any child control? Please see the code below that did not work for me. Also, since i have many different controls, I rather have a "proper" solution: I rather not attach handlers to each instance of a control in my window.

<Window x:Class="KeyTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

<Window.CommandBindings>
    <CommandBinding Command="Help"
                    CanExecute="HelpCanExecute"
                    Executed="HelpExecuted" />
</Window.CommandBindings>

<Window.InputBindings>
    <KeyBinding Command="Help" Key="H" />
</Window.InputBindings>

<Grid>
    <WrapPanel>
        <TextBox Name="myLOG" Width="300" Height="200" Background="LightBlue" />
        <TextBox Name="myINPUT" Width="300" Height="200" />
        <Button Content="JUST FOR FUN" />
    </WrapPanel>
</Grid>

And for C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace KeyTest
{
   /// <summary>
   /// Interaction logic for MainWindow.xaml
   /// </summary>
   public partial class MainWindow : Window
   {
      private void HelpCanExecute(object sender, CanExecuteRoutedEventArgs e)
      {
         myLOG.Text += "HELP CAN EXECUTE\n";
         e.CanExecute = true;
         e.Handled = true;
      }

      private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
      {
         myLOG.Text += "HELP  EXECUTED!!!\n";
         e.Handled = true;
      }

      public void myKeyUpHandler(Object sender, KeyEventArgs args)
      {
         myLOG.Text += "KEY UP EVENT! " + args.Key + "\n";
      }

      public MainWindow()
      {
         InitializeComponent();
         this.KeyUp += new KeyEventHandler(myKeyUpHandler);
      }
   }
}

When the focus is in text box, pressing "h" triggers the command, even though i want 'h' to only go to the text box. Also, when inside textbox, pressing any alpha numeric key fires the KeyUp event, even though as far as I understand, textbox should have handled=true that event!

Thanks for help!

You need to investigate using the preview event types. They happen before other controls will handle the events. Then you want to stop the events bubbling. I belive you are doing that correctly with e.Handled.

Investigate this: http://msdn.microsoft.com/en-us/library/system.windows.input.keyboard.previewkeydown.aspx

Not sure how to do it in xaml for what you want to do. The expressions blend libraries can be quite helpful for spawning commands off of events. See here: http://jacokarsten.wordpress.com/2009/03/27/applying-command-binding-to-any-control-and-any-event/

Dude I think you need to use previewKeyDown or PreviewKeyUp Event instead of a keyup event here because PreviewKeydown and PreviewKeyup Event produce tunneling effect(OPPOSITE of bubbling effect where events where fired starting from the RootParent of the control which fired the event down the to control which originally fired the event(also know as original source)). you can take advantage of this tunneling effect for handling events rather that using events which are fired via bubbling effect. Another thing is that PreviewKeyDown and PrevieKeyup events where fired before keydown events occur. This could let you intercept the event in the cleanest way.

Another thing, I think you need to check the original source of the event so that you could select the controls that could fire this events.

Here is a sample code

 public void nameOfCotrol_PreviewKeyDown(object sender, RoutedEventArgs e)
 {
    if((e.OriginalSource as Control).Name == "NameOfControls That would be allowed to fire the event")
    {
        You're stuff to be done here
    }
    else
    {
        e.handled = true;
     }
 }

I hope this could help in a small way. Thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM