我如何制作Select();在每个应用程序上鼠标在屏幕上?

时间:2013-05-26 16:26:41

标签: c# winforms

我在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”的垃圾回收委托进行了回调。这可能会导致应用程序崩溃,损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须将它们保持活动状态,直到确保它们永远不会被调用为止。

1 个答案:

答案 0 :(得分: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;

并将hook方法更改为:

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;
}