好吧,所以我无法抗拒这里的挑战 :) 编写了一个小程序,可以满足您的需求。
它是如何工作的:SetWindowsHookEx
让你放置一个全局鼠标钩子。现在,你得到了X
,Y
然后使用WindowFromPoint得到hWnd
你的目标窗口。从这里你可以做任何你喜欢的事情,在我的例子中,我发送了一个WM_GETTEXT
来获取它的标题。
这就是程序看起来执行的样子。单击Begin
后,它将全局查找右键单击事件,并将它们添加到列表框中。注意:它需要是一个窗体应用程序,钩子不适用于控制台应用程序。
用法(只需创建一个默认的 WinForms 项目并将其更改为此):
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
RMouseListener _native;
private void button1_Click(object sender, EventArgs e)
{//start
_native = new RMouseListener();
_native.RButtonClicked +=
new EventHandler<SysMouseEventInfo>(_native_RButtonClicked);
}
private void button2_Click(object sender, EventArgs e)
{//stop
_native.Close();
}
void _native_RButtonClicked(object sender, SysMouseEventInfo e)
{
listBox1.Items.Add(e.WindowTitle);
}
}
实现(这是一些代码;))
public class SysMouseEventInfo : EventArgs
{
public string WindowTitle { get; set; }
}
public class RMouseListener
{
public RMouseListener()
{
this.CallBack += new HookProc(MouseEvents);
//Module mod = Assembly.GetExecutingAssembly().GetModules()[0];
//IntPtr hMod = Marshal.GetHINSTANCE(mod);
using (Process process = Process.GetCurrentProcess())
using (ProcessModule module = process.MainModule)
{
IntPtr hModule = GetModuleHandle(module.ModuleName);
_hook = SetWindowsHookEx(WH_MOUSE_LL, this.CallBack, hModule, 0);
//if (_hook != IntPtr.Zero)
//{
// Console.WriteLine("Started");
//}
}
}
int WH_MOUSE_LL = 14;
int HC_ACTION = 0;
HookProc CallBack = null;
IntPtr _hook = IntPtr.Zero;
public event EventHandler<SysMouseEventInfo> RButtonClicked;
int MouseEvents(int code, IntPtr wParam, IntPtr lParam)
{
//Console.WriteLine("Called");
if (code < 0)
return CallNextHookEx(_hook, code, wParam, lParam);
if (code == this.HC_ACTION)
{
// Left button pressed somewhere
if (wParam.ToInt32() == (uint)WM.WM_RBUTTONDOWN)
{
MSLLHOOKSTRUCT ms = new MSLLHOOKSTRUCT();
ms = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
IntPtr win = WindowFromPoint(ms.pt);
string title = GetWindowTextRaw(win);
if (RButtonClicked != null)
{
RButtonClicked(this, new SysMouseEventInfo { WindowTitle = title });
}
}
}
return CallNextHookEx(_hook, code, wParam, lParam);
}
public void Close()
{
if (_hook != IntPtr.Zero)
{
UnhookWindowsHookEx(_hook);
}
}
public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(int xPoint, int yPoint);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(POINT Point);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] StringBuilder lParam);
public static string GetWindowTextRaw(IntPtr hwnd)
{
// Allocate correct string length first
//int length = (int)SendMessage(hwnd, (int)WM.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
StringBuilder sb = new StringBuilder(65535);//THIS COULD BE BAD. Maybe you shoudl get the length
SendMessage(hwnd, (int)WM.WM_GETTEXT, (IntPtr)sb.Capacity, sb);
return sb.ToString();
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MSLLHOOKSTRUCT
{
public POINT pt;
public int mouseData;
public int flags;
public int time;
public UIntPtr dwExtraInfo;
}
enum WM : uint
{//all windows messages here
WM_RBUTTONDOWN = 0x0204,
WM_GETTEXT = 0x000D,
WM_GETTEXTLENGTH = 0x000E
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}