使用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);
}
}
}
我也无法通过引用传递表单,因为'这个'是只读的。
如何更改低级键盘钩子中的表单属性?