我安装了一个线程专用的windows钩子来监视发送给WndProc的消息。它起初工作。但是,在我按Tab键大约19次以将焦点移到窗体上之后,我的钩子回调函数不再被称为。无论我是快速还是缓慢地按下Tab,都会发生这种情况。任何人都可以解释究竟发生了什么?多次按Tab键后不再调用线程挂接程序。为什么?
下面是我写的代码。我在Windows 7 64位上测试了它。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace HookTest
{
static class Program
{
private const int WH_CALLWNDPROC = 4;
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private class MainForm : Form
{
private Button button1;
private TextBox textBox1;
public MainForm()
{
this.button1 = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(12, 38);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "Button 1";
this.button1.UseVisualStyleBackColor = true;
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(12, 12);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
//
// MainForm
//
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button1);
this.Name = "MainForm";
this.Text = "Main Form";
this.ResumeLayout(false);
this.PerformLayout();
}
}
private static IntPtr hWndProcHook = IntPtr.Zero;
private static int messageCount = 0;
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetCurrentThreadId();
[DllImport("User32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SetWindowsHookEx(int idHook,
HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
InstallHook();
Application.Run(new MainForm());
UninstallHook();
}
private static void InstallHook()
{
if (Program.hWndProcHook == IntPtr.Zero)
{
Console.WriteLine("Hooking...");
Program.hWndProcHook = SetWindowsHookEx(
WH_CALLWNDPROC,
WndProcHookCallback,
GetModuleHandle(null),
GetCurrentThreadId());
if(Program.hWndProcHook != IntPtr.Zero)
Console.WriteLine("Hooked successfully.");
else
Console.WriteLine("Failed to hook.");
}
}
private static void UninstallHook()
{
if (Program.hWndProcHook != IntPtr.Zero)
{
Console.WriteLine("Unhooking...");
if (UnhookWindowsHookEx(Program.hWndProcHook))
Console.WriteLine("Unhooked successfully.");
else
Console.WriteLine("Failed to unhook.");
Program.hWndProcHook = IntPtr.Zero;
}
}
private static IntPtr WndProcHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
Console.WriteLine("WndProcHookCallback {0}", Program.messageCount++);
return CallNextHookEx(Program.hWndProcHook, nCode, wParam, lParam);
}
}
}
您的代码对我来说工作得很好,而且我按Tab超过19次。有没有其他信息可以提供?你如何验证它不起作用?我刚刚观看了VS中的输出窗格。 –
我通过在调试模式下运行并查看输出窗口来验证它是否工作正常。如果钩子正在工作,它应该将“WndProcHookCallback#”写入输出窗口,其中#是递增的整数。如果没有更多这样的消息被写入输出窗口,挂钩程序不再被调用。 –
这个钩子没有做任何有用的事情。钩子回调中的* real *代码是什么样的? –