【问题标题】:WPF Application wide capture of key up/down eventsWPF 应用程序范围内的键向上/向下事件捕获
【发布时间】:2011-05-19 21:14:17
【问题描述】:

我试图在我的 WPF 应用程序中的任何位置捕获按键事件,无论哪个 UI 元素具有焦点。目前我没有运气。谁能建议一些我可能没有尝试过的策略?或者,理想情况下,提供类似“哦,这很简单,你就这样做”这样的答案。

它是一个分布式应用程序,它有一个聊天系统。我正在寻找的效果是用户可以随时开始输入聊天消息,而无需切换到标准聊天框。我将使用 FormattedText 对象自己在应用程序中显示他们的消息。这很重要,因为这意味着应用程序中的任何地方都没有文本输入元素。

我的 XAML 结构大致如下:

<MainWindow>
  <Canvas 1>
    <Canvas 2>
      <Image 1 />
    </Canvas 2>
    <Image 2 />
  </Canvas 1>
</MainWindow>

我以编程方式将元素添加到 Canvas 2 中,并操作 Image 2,这就是它具有这种结构的原因。

我尝试将 KeyDown、KeyUp 和 Preview 事件添加到 MainWindow 和 Canvas 1,但它们似乎都没有触发(我检查断点)。我也在这里阅读了另一个相关问题后,尝试在 Loaded() 方法中手动将焦点设置在主窗口上。

我知道这个网站上有很多相关的问题,但他们没有帮助我,因为:

  • 没有任何答案(我的问题会得到解答吗?)
  • 他们假设一个文本输入小部件并且对冒泡事件感兴趣
  • 他们希望为少量键绑定键 - 我想捕获任何键
  • 他们有兴趣在捕获事件后检测 control/shift/alt 键是否按下

感谢您花时间阅读我冗长的帖子,并感谢您的建议。

更新(在 Rachel 的评论之后)当我放入一个 TextBox 并将焦点设置到 TextBox 时,将触发 MainWindow 级别的一个键事件方法。这样就可以像宣传的那样工作了。

但是,我真的希望应用程序中根本没有显式的文本输入小部件。我希望用户能够开始输入来撰写消息。

【问题讨论】:

标签: c# wpf events key


【解决方案1】:

我通常会在 MainWindow 中添加一个 PreviewKeyDown 事件。

也许您的问题是您没有任何控件可以在您的应用程序上接受键盘焦点。如果您将 TextBox 添加到 MainWindow 并在那里设置焦点,您会得到相同的结果吗?

【讨论】:

  • 这确实有效(在主窗口中添加一个文本框,PreviewKeyDown,焦点到文本框,按一个键)。我正在更新主要帖子来说明这一点。但是,如果可能,我想避免在应用程序中使用 TextBox。您关于某些控件不接受键盘焦点的观点很重要。有什么方法可以强制非文本输入控件的键盘焦点?
  • 我刚刚测试过,即使没有对象,我也可以有一个空白窗口来获取 PreviewKeyPressed 事件。 XAML 代码中的&lt;MainWindow&gt; 标记有什么特别之处吗?
【解决方案2】:

一点点修修补补让我得到了这个:

XAML:

<Window x:Class="KeyInput.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="100" Width="225">
    <Canvas>
        <Grid>
            <Label Name="test" Content="Empty" />
        </Grid>
    </Canvas>
</Window>

CS:

using System.Windows;
using System.Windows.Input;

namespace KeyInput
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.KeyDown += new KeyEventHandler(OnButtonKeyDown);
        }

        private void OnButtonKeyDown(object sender, KeyEventArgs e)
        {
            test.Content = test.Content + e.Key.ToString();
        }
    }
}

这会打印出“Shift”之类的内容,因此您显然必须使用开关……但它有一个收集按键的文本框。

【讨论】:

    【解决方案3】:

    RachelWernerCD 的回答的启发下,我设法解决了这个问题。正如他们所展示的,在 MainWindow 级别进行事件捕获确实有效。问题是我忽略了在加载 MainWindow 之前我有一个对话框,这似乎干扰了 MainWindow 上的正常键盘焦点。将显式 Keyboard.focus() 放入 Loaded() 方法还为时过早。我通过将 Keyboard.focus() 放在 MainWindow_ContentRendered() 方法中解决了这个问题。

    现在一切都很好(直到下一期)。感谢您的帮助。

    【讨论】:

      猜你喜欢
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-07
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 2019-05-03
      相关资源
      最近更新 更多