全局键盘挂钩有效,但全局 shell 挂钩失败
我有两段代码非常相似,因为它们注册了全局钩子。
注册全局键盘钩子:
public class KeyboardHook : IDisposable
{
#region Events
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void HookEventHandler(object sender, KeyboardHookEventArgs e);
public event HookEventHandler KeyDown;
public event HookEventHandler KeyUp;
#endregion
#region Constants
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_SYSKEYDOWN = 0x0104;
private LowLevelKeyboardProc _proc = null;
private static IntPtr _hookID = IntPtr.Zero;
#endregion
#region Imports
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion
#region Constructor
public KeyboardHook()
{
_proc = new LowLevelKeyboardProc(HookCallback);
_hookID = SetHook(_proc);
}
#endregion
#region Methods
private IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
//if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN))
{
int vkCode = Marshal.ReadInt32(lParam);
WinForms.Keys key = (WinForms.Keys)vkCode;
if (this.KeyDown != null)
this.KeyDown(this, new KeyboardHookEventArgs(vkCode));
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
#endregion
#region Destructor
public void Dispose()
{
UnhookWindowsHookEx(_hookID);
}
#endregion
}
注册全局 shell 钩子:
public enum ShellEvents
{
HSHELL_WINDOWCREATED = 1,
HSHELL_WINDOWDESTROYED = 2,
HSHELL_ACTIVATESHELLWINDOW = 3,
HSHELL_WINDOWACTIVATED = 4,
HSHELL_GETMINRECT = 5,
HSHELL_REDRAW = 6,
HSHELL_TASKMAN = 7,
HSHELL_LANGUAGE = 8,
HSHELL_ACCESSIBILITYSTATE = 11
}
public class ShellHook
{
#region Events
private delegate IntPtr ShellProc(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void HookEventHandler(object sender, ShellHookEventArgs e);
public event HookEventHandler WindowActivated;
#endregion
#region Constants
private const int WH_SHELL = 10;
private ShellProc _proc = null;
private static IntPtr _hookID = IntPtr.Zero;
#endregion
#region Imports
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
ShellProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
#endregion
#region Fields
#endregion
#region Constructor
public ShellHook()
{
_proc = new ShellProc(HookCallback);
_hookID = SetHook(_proc);
}
#endregion
#region Methods
private IntPtr SetHook(ShellProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_SHELL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam.Equals(ShellEvents.HSHELL_WINDOWACTIVATED))
{
string windowTitle = GetWindowTitle(wParam);
if (this.WindowActivated != null)
this.WindowActivated(this, new ShellHookEventArgs(windowTitle));
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private string GetWindowTitle(IntPtr hWnd)
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
if (GetWindowText(hWnd, Buff, nChars) > 0)
{
return Buff.ToString();
}
return null;
}
#endregion
#region Destructor
public void Dispose()
{
UnhookWindowsHookEx(_hookID);
}
#endregion
}
由于某种原因,键盘钩子有效,但 shell 钩子失败(SetWindowsHookEx
返回 0
并且回调永远不会到达)。
有什么想法吗?
I have two pieces of code which are very similar in that they register global hooks.
Registering global keyboard hook:
public class KeyboardHook : IDisposable
{
#region Events
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void HookEventHandler(object sender, KeyboardHookEventArgs e);
public event HookEventHandler KeyDown;
public event HookEventHandler KeyUp;
#endregion
#region Constants
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_SYSKEYDOWN = 0x0104;
private LowLevelKeyboardProc _proc = null;
private static IntPtr _hookID = IntPtr.Zero;
#endregion
#region Imports
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion
#region Constructor
public KeyboardHook()
{
_proc = new LowLevelKeyboardProc(HookCallback);
_hookID = SetHook(_proc);
}
#endregion
#region Methods
private IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
//if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN))
{
int vkCode = Marshal.ReadInt32(lParam);
WinForms.Keys key = (WinForms.Keys)vkCode;
if (this.KeyDown != null)
this.KeyDown(this, new KeyboardHookEventArgs(vkCode));
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
#endregion
#region Destructor
public void Dispose()
{
UnhookWindowsHookEx(_hookID);
}
#endregion
}
Registering global shell hook:
public enum ShellEvents
{
HSHELL_WINDOWCREATED = 1,
HSHELL_WINDOWDESTROYED = 2,
HSHELL_ACTIVATESHELLWINDOW = 3,
HSHELL_WINDOWACTIVATED = 4,
HSHELL_GETMINRECT = 5,
HSHELL_REDRAW = 6,
HSHELL_TASKMAN = 7,
HSHELL_LANGUAGE = 8,
HSHELL_ACCESSIBILITYSTATE = 11
}
public class ShellHook
{
#region Events
private delegate IntPtr ShellProc(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void HookEventHandler(object sender, ShellHookEventArgs e);
public event HookEventHandler WindowActivated;
#endregion
#region Constants
private const int WH_SHELL = 10;
private ShellProc _proc = null;
private static IntPtr _hookID = IntPtr.Zero;
#endregion
#region Imports
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
ShellProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
#endregion
#region Fields
#endregion
#region Constructor
public ShellHook()
{
_proc = new ShellProc(HookCallback);
_hookID = SetHook(_proc);
}
#endregion
#region Methods
private IntPtr SetHook(ShellProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_SHELL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam.Equals(ShellEvents.HSHELL_WINDOWACTIVATED))
{
string windowTitle = GetWindowTitle(wParam);
if (this.WindowActivated != null)
this.WindowActivated(this, new ShellHookEventArgs(windowTitle));
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private string GetWindowTitle(IntPtr hWnd)
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
if (GetWindowText(hWnd, Buff, nChars) > 0)
{
return Buff.ToString();
}
return null;
}
#endregion
#region Destructor
public void Dispose()
{
UnhookWindowsHookEx(_hookID);
}
#endregion
}
For some reason, the keyboard hook works, but the shell hook fails (SetWindowsHookEx
returns 0
and the callback is never reached).
Any ideas why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想我会回答我自己的问题。 pinvoke.net 的这句话解释了为什么......
I think I'll answer my own question. This quote from pinvoke.net explains why...