【问题标题】:Is it possible to handle Keyboard/Mouse events application wide in WPF?是否可以在 WPF 中处理应用程序范围内的键盘/鼠标事件?
【发布时间】:2016-06-01 15:36:36
【问题描述】:

我意识到这个问题可能以前被问过,但我找不到这十年的答案,所以我希望答案已经改变并且是“是”。

我正在开发一个没有 GUI 可言的应用程序,因此不存在用于“捕获”鼠标或键盘事件的“主窗口”。

我查看了 Gma.HookManager 项目,但它都是为 WinForms 编写的,并且试图使其适应 WPF 让我想把酗酒作为一种爱好......

是否可以将鼠标/事件处理程序写入实际的应用程序类,这样,即使应用程序中没有窗口或其他 GUI,这些事件也会在按键和/或鼠标事件时接收?

【问题讨论】:

  • 为什么不将 MainWindow 用于其中一个窗口?
  • @Paparazzi 因为如果其他窗口之一获得焦点会发生什么?键盘/鼠标事件不会传递到“主”窗口,对吧?所以这行不通。无论哪个窗口有焦点(或者即使没有一个窗口有焦点),我都需要将事件传递给应用程序。
  • 然后澄清问题。你说没有“主”窗口。是什么阻止您拥有多个事件处理程序并将其传递给“应用程序” - 再次不清楚。
  • @Paparazzi 澄清。无论应用程序是否具有 GUI,我都希望它能够正常工作。不过,它仍然必须是 WPF - 它不是控制台应用程序。
  • 我想你想要的是一个低级的钩子:SetWindowsHookEx

标签: c# wpf mouseevent keyboard-events


【解决方案1】:

我编写了一个快速实用程序类来使用 gma 在 wpf 中完成您需要的工作。

确保在项目中添加对 gma 库和 windows 窗体的引用。我很快测试了它,它运行良好,如果您有任何问题,请告诉我。新的堆栈溢出顺便说一句不确定我是否收到通知。

编辑:如果您将围绕 gma 事件创建我自己的包装器,我的解决方案包括使用系统 KeyInterop 类将密钥数据从 windows 窗体键事件转换为 wpf 键数据。

这是课程

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Gma.UserActivityMonitor;
using System.Windows.Input;
using System.Windows.Forms;

namespace WpfApplicationTest
{
public class HookManager
{

    private GlobalEventProvider _provider;

    public event EventHandler<HookKeyArgs> KeyDown;

    public event EventHandler<HookKeyArgs> KeyUp;

    public HookManager()
    {
        _provider = new Gma.UserActivityMonitor.GlobalEventProvider();

        _provider.KeyDown += _provider_KeyDown;
        _provider.KeyUp += _provider_KeyUp;
    }

    void _provider_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
    {
        if (KeyUp != null)
        {
            KeyUp(this, new HookKeyArgs(convertWinFormsKey(e.KeyData), false, true));
        }
    }

    void _provider_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
    {
        if (KeyDown != null)
        {
            KeyDown(this, new HookKeyArgs(convertWinFormsKey(e.KeyData), true, false));
        }
    }

    System.Windows.Input.Key convertWinFormsKey(System.Windows.Forms.Keys keyMeta)
    {
        Keys formsKey = keyMeta;
        return KeyInterop.KeyFromVirtualKey((int)formsKey);
    }
}

public class HookKeyArgs : EventArgs
{
    public System.Windows.Input.Key KeyPressed {get; private set;}
    public bool IsDown { get; private set; }

    public bool IsUp { get; private set; }

    public HookKeyArgs(System.Windows.Input.Key keyPressed, bool isDown, bool isUp)
    {
        this.KeyPressed = keyPressed;
        this.IsDown = isDown;
        this.IsUp = isUp;
    }


}}

这是一个使用它的例子。

    public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var hookManager = new HookManager();

        hookManager.KeyUp += hookManager_KeyUp;
    }

    void hookManager_KeyUp(object sender, HookKeyArgs e)
    {
        MessageBox.Show("key pressed: " + e.KeyPressed.ToString());
    }
}}

【讨论】:

    猜你喜欢
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    • 2021-12-26
    • 2013-02-13
    • 2011-05-19
    • 1970-01-01
    相关资源
    最近更新 更多