【问题标题】:How can i make Select(); on each application the mouse is on screen?我怎样才能使 Select();在每个应用程序上,鼠标都在屏幕上?
【发布时间】:2015-09-18 17:21:51
【问题描述】:

我在 Form1 的顶部做了这个:

globalKeyboardHook gkh;

在加载事件中:

private void Form1_Load(object sender, EventArgs e)
{
    gkh = new globalKeyboardHook();
    gkh.HookedKeys.Add(Keys.M);
    gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
    gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
}

然后在底部:

void gkh_KeyDown(object sender, KeyEventArgs e)
{
    // e.KeyCode.ToString() is the KeyCode of the pressed key
    e.Handled = true;
    if ((e.KeyCode == System.Windows.Forms.Keys.LControlKey) || (e.KeyCode == System.Windows.Forms.Keys.RControlKey))
    {
        controlDown = true;
    }

    if (e.KeyCode == System.Windows.Forms.Keys.M && controlDown)
    {
        // Do CTRL-M action
        if (mf == null)
        {
            //mf = new MagnifierMainForm();
            mf = new MagnifierMainForm(false);
            mf.StartPosition = FormStartPosition.Manual;
            mf.Location = Control.MousePosition;
            //mf.Show();

            this.Select();
        }
        else if (mf.IsDisposed)
        {
            mf = new MagnifierMainForm(false);
            mf.StartPosition = FormStartPosition.Manual;
            mf.Location = Control.MousePosition;
            //mf.Show();
        }
        else
        {
            mf.Close();
            mf = null;
        }
    }
}

        void gkh_KeyUp(object sender, KeyEventArgs e)
        {
            controlDown = false;
        }

例如,当我运行我的应用程序并单击提示命令窗口然后单击 CTRL+M 或什至在几秒钟后没有单击任何内容时,我遇到了异常:

CallbackOnCollectedDelegate 对“ScreenVideoRecorder!Utilities.globalKeyboardHook+keyboardHookProc::Invoke”类型的垃圾收集委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须使它们保持活动状态,直到保证它们永远不会存在

检测到 CallbackOnCollectedDelegate 消息:对“ScreenVideoRecorder!Utilities.globalKeyboardHook+keyboardHookProc::Invoke”类型的垃圾收集委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须使它们保持活动状态,直到保证它们永远不会被调用。

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    我相信您正在寻找全局键盘挂钩。 这是simple C# example of usage

    如果你使用上面例子中的globalKeyboardHook类,你需要做4件事:

    首先将同名的 .cs 文件添加到您的项目中(并且由于该代码中存在错误,至少在 2007 年 5 月 30 日的版本中,请按以下方式修改它- 根据会员 4120854 的评论):

    线下

    public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
    

    添加这一行

    private keyboardHookProc _keyboardHookProc;
    

    并将钩子方法更改为如下所示:

    public void hook()
    {
        IntPtr hInstance = LoadLibrary("User32");
        _keyboardHookProc = new keyboardHookProc(hookProc);
        hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _keyboardHookProc, hInstance, 0);
    }
    

    其次,在你的Form类中添加这样的私有成员变量

    globalKeyboardHook gkh = new globalKeyboardHook();
    

    第三,在您的 Form_Load(或您想要开始挂钩键的其他位置)上,将您想要的键添加到 gkh 类的 HookedKeys 集合属性并订阅 KeyDown 和/ 或 gkh 类的 KeyUp 事件,如下所示:

    private void Form1_Load(object sender, EventArgs e) {
        gkh.HookedKeys.Add(Keys.LControlKey);
        gkh.HookedKeys.Add(Keys.RControlKey);
        gkh.HookedKeys.Add(Keys.M);
        gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
        gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
    }
    

    第四,然后您可以在 KeyUp 或 KeyDown 处理程序中执行您想要的操作,将 e.Handled 设置为 true 以停止在系统上传播键事件,如下所示:

    void gkh_KeyUp(object sender, KeyEventArgs e) { // e.KeyCode.ToString() 是释放键的KeyCode e.Handled = true; }

        void gkh_KeyDown(object sender, KeyEventArgs e) {
            // e.KeyCode.ToString() is the KeyCode of the pressed key
            e.Handled = true;
        }
    

    要对特定的组合键执行某些操作,您需要在变量中记录键的状态,并在 KeyDown 时检查两个(或所有)键是否已关闭。因此,对于“CTRL-M”,您将添加一个成员变量

    bool controlDown = false;
    

    然后您可以将此代码添加到您的 KeyDown 事件处理程序中

    if ((e.KeyCode == System.Windows.Forms.Keys.LControlKey) || (e.KeyCode == System.Windows.Forms.Keys.RControlKey))
    {
        controlDown = true;
    }
    
    if (e.KeyCode == System.Windows.Forms.Keys.M && controlDown)
    {
        // Do CTRL-M action
    }
    

    并且您需要在 KeyUp 事件处理程序中添加这个

    if ((e.KeyCode == System.Windows.Forms.Keys.LControlKey) || (e.KeyCode == System.Windows.Forms.Keys.RControlKey))
    {
        controlDown = false;
    }
    

    【讨论】:

    • Bikonja 好的,我查看了链接并将其添加到我的代码中。但我不确定如何使它工作尝试将它添加到我的代码中。你能再看看我的问题吗?我编辑了它?
    • 您应该将密钥处理放在其中一个(或两个)事件中:gkh.KeyDown += new KeyEventHandler(gkh_KeyDown); gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
    • @Bikonja - 请将示例代码添加到您的答案中。它将更加明显且格式正确。
    • @ChrisF 我使用 URL 中的类使用示例代码编辑了我的答案,但是如果我添加完整的钩子代码,答案会太大,所以我只是使用了使用类的代码。
    • 我遇到了一个异常。我将使用我更改的代码更新我的问题。
    猜你喜欢
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多