【问题标题】:Raising Keyboard events via an Interface in WPF通过 WPF 中的接口引发键盘事件
【发布时间】:2012-07-12 12:06:33
【问题描述】:

我正在尝试在 WPF 中构建一个应用程序,我想在其中处理来自连接到单台计算机的多个键盘的输入(KeyPress 事件)。所以,我有一个类,我在其中重写 WndProc() 方法,并且能够接收来自不同键盘设备的输入。在执行此操作时,我使用 MainWindow 句柄注册此类,因此窗口可以接收 CLR 键盘事件。但这不是问题。

问题是我现在正在 WPF 中开发UserControl,它也可以响应这些多键盘事件。这些UserControls 将在同一个窗口中实例化,但我正在考虑通过接口发送事件(尤其是RoutedEvents)。因此,我的自定义 UserControl 类只是实现了接口,我很高兴。

你们知道如何做到这一点吗,我对 WPF 真的很陌生,所以我遇到了一些困难。

提前致谢!!!

【问题讨论】:

  • 为什么要添加额外的接口步骤来“发送”事件。只需像往常一样将侦听器附加到它们。
  • 因为在这种情况下,我的 UserControl 类必须知道 KeyboardManager 类实例(实际上是引发所有键盘事件),并且此 KeyboardManager 在 MainWindow 中被实例化。
  • 您的用户控件必须以一种或另一种方式挂钩到事件。此外,根据您的描述,所有内容(用户控件、键盘管理器等)都在同一个窗口中,因此您的控件与管理器处于同一范围内。除非您有更宏大的计划,否则只需将其连接起来并完成它。
  • 是的,我实际上可以这样做,因为这个 KeyboardManager 实例在同一个范围内。但为了保持分离和清洁,我决定采用界面方式。
  • 无论如何我已经实现了一个 CLR 事件,它通知我的自定义 UserControl 类的键盘事件,我可以这样做,因为我确切地知道每个键盘设备的输入焦点(用户控件)是什么,并且使用这个想法,我实际上可以在我想调用的确切类中调用接口方法。无论如何感谢 A.R.为您的建议。

标签: c# wpf routed-events


【解决方案1】:

所以,我想出了如何做到这一点。我有一个名为BIFUserControl 的类,它实现了我创建的接口,用于处理来自连接到同一台计算机的多个键盘的事件。该接口称为IMultiKeyboardEvents。我还有一个只读集合,它将每个键盘设备的当前状态存储为BIFKeyboardDevice 类的实例。

所以,基本上我知道每个键盘设备的输入焦点是什么,它表示为BIFKeyboardDevice 类中的一个属性。因此,当从键盘管理器类BIFKeyboardManager 引发 CLR 事件时,我实际上可以在具有特定控件输入焦点的确切类中调用接口方法实现。

下面是自定义用户控件类实现的接口IMultiKeyboardEvents的代码:

public interface IMultiKeyboardEvents  
{
    event MultiKeyEventHandler MultiKeyDown;
    event MultiKeyEventHandler MultiKeyUp;

    void OnMultiKeyDown(MultiKeyEventArgs);
    void OnMultiKeyDown(MultiKeyEventArgs);
}

在覆盖 WndProc() 方法的键盘管理器类中,我有一个处理输入事件的方法,如下所示:

void ProcessInput(Message message)
{
    // Code sample which raises just the key down event
    switch (rawInput.keyboard.Message)
    {
        case (uint) BIFWin32.WindowMessage.WM_KEYDOWN:
        {
            if (BIFDeviceCollections.MouseCollection[ID].MouseFocusElement is IMultiKeyboardEvents)
            {
                IMultiKeyboardEvents widget = 
                (IMultiKeyboardEvent)BIFDeviceCollections.MouseCollection[ID].MouseFocusedElement;
                widget.OnMultiKeyDown(eventArgs);
            }
            break;
        }
        case (uint) BIFWin32.WindowMessage.WM_KEYUP:
        {
            if (BIFDeviceCollections.MouseCollection[ID].MouseFocusElement is IMultiKeyboardEvents)
            {
                IMultiKeyboardEvents widget = 
                (IMultiKeyboardEvent)BIFDeviceCollections.MouseCollection[ID].MouseFocusedElement;
                widget.OnMultiKeyUp(eventArgs);
            }
            break;
        }
    }
}

这只是在我的 UserControl 类中调用 OnMultiKeyDown 方法的实现,我不必使用用户控件类中的键盘管理器实例并连接事件来监听它们。另外,因为我已经收集了所有设备对象(鼠标和键盘),并且它们维护一个字段,说明每个设备的当前焦点元素是什么,并且我已经配对了每个鼠标和键盘设备,所以我可以直接使用它引发事件的信息。

【讨论】:

  • 发布一些代码。我想看看一切是如何连接起来的,以及界面如何让它“更干净”
  • 嗨,A.R.我已经发布了一些代码。请看一下,我真的希望它足够了,我也感谢您的建议:-)
  • 好的,我明白你在做什么了。所以接口的实现者(IMultiKeyboard...)实际上并没有处理任何事件(因为它们没有在监听),你只是在其他东西处理实际事件时发送一些参数。
  • 那么为什么你的接口定义上定义了两个事件呢?这些是否在您的代码中的其他地方使用?
  • 是的,正是……接口的实现者实际上并不处理任何事件。它类似于简单的System.Windows.Controls.Button 类,它从WPF 框架中获取所有输入事件(鼠标、触摸等),但反过来又为程序员提供了其他事件,例如Click。因此,就我而言,BIFUserControl 类实际上是一个基类,我将使用它来开发更具体的多键盘小部件(例如多键盘便利贴)。因此,每当有输入事件(例如按键)时,UserControl 类都会执行一些操作并引发一些其他事件
猜你喜欢
  • 2016-01-11
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 2015-08-27
相关资源
最近更新 更多