如何在低级键盘钩子中更改表单?

时间:2016-03-12 16:08:26

标签: c# winforms static delegates keyboard-hook

使用following implementation,我有一个低级键盘钩子来检测表格外部的键盘按下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    class KeyboardHook
    {
        //DLLs for global keyboard hooking
        [DllImport("user32.dll")]
        static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);
        [DllImport("user32.dll")]
        static extern bool UnhookWindowsHookEx(IntPtr hInstance);
        [DllImport("user32.dll")]
        static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);
        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
        private LowLevelKeyboardProc _proc = hookProc;
        private static IntPtr hhook = IntPtr.Zero;
        public static bool ctrlPressed = false;


        public void SetHook()
        {
            IntPtr hInstance = LoadLibrary("User32");
            hhook = SetWindowsHookEx(13, _proc, hInstance, 0);
        }
        public static void UnHook()
        {
            UnhookWindowsHookEx(hhook);
        }
        public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            if (code >= 0 && wParam == (IntPtr)0x100)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                if (vkCode == 162 || vkCode == 163)
                {
                    ctrlPressed = true;
                }
                else if (vkCode == 88 && ctrlPressed == true)
                {
                    MessageBox.Show("ctrl+x clicked");
                    //change form property ??
                }
                else
                {
                    ctrlPressed = false;
                }
                return (IntPtr)1;
            }
            else
                return CallNextHookEx(hhook, code, (int)wParam, lParam);
        }
    }

}

我的问题是,我无法在钩子内更改表单属性。

我通常会在我的表单中实例化钩子,如下所示:

KeyboardHook hook = new KeyboardHook();

但是为了获取我的表单,我会尝试在构造函数中传递它

KeyboardHook hook = new KeyboardHook(this);

这将导致我在KeyboardHook中创建一个静态Form成员,并将其分配给构造函数的输入参数。它必须是静态的,因为所有的钩子方法都是静态的。但这不起作用,并且未观察到更改表单的属性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    class KeyboardHook
    {
        //DLLs for global keyboard hooking
        [DllImport("user32.dll")]
        static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);
        [DllImport("user32.dll")]
        static extern bool UnhookWindowsHookEx(IntPtr hInstance);
        [DllImport("user32.dll")]
        static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);
        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
        private LowLevelKeyboardProc _proc = hookProc;
        private static IntPtr hhook = IntPtr.Zero;
        public static bool ctrlPressed = false;
        public static Form form; //added


        public void SetHook(Form form_in) //added
        {
            IntPtr hInstance = LoadLibrary("User32");
            hhook = SetWindowsHookEx(13, _proc, hInstance, 0);
            form = form_in; //added
        }
        public static void UnHook()
        {
            UnhookWindowsHookEx(hhook);
        }
        public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            if (code >= 0 && wParam == (IntPtr)0x100)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                if (vkCode == 162 || vkCode == 163)
                {
                    ctrlPressed = true;
                }
                else if (vkCode == 88 && ctrlPressed == true)
                {
                    MessageBox.Show("ctrl+x clicked");
                    form.ChangeSomeProperty();  //this does not work
                }
                else
                {
                    ctrlPressed = false;
                }
                return (IntPtr)1;
            }
            else
                return CallNextHookEx(hhook, code, (int)wParam, lParam);
        }
    }

}

我也无法通过引用传递表单,因为'这个'是只读的。
如何更改低级键盘钩子中的表单属性?

0 个答案:

没有答案