我想知道是否有人能够深入了解如何在Winspector Spy中实现窗口选择器。基本上,我想提供一个我可以鼠标按下的面板,拖动到另一个进程窗口(或子窗口)并从中获取类似HWND的内容。理想情况下,我会在C#中执行此操作,但如果只能通过包装C API来实现,那么我可以在C ++中完成。
我搞乱了DragDrop事件并在C#中用鼠标向下调用DoDragDrop,但我不确定这是否能给我我想要的东西。获取鼠标的全局X / Y位置并找到该位置的最顶层窗口会更容易吗?在给定x,y参数的情况下,是否存在自动执行此操作的API?编辑:刚刚发现后一个问题的WindowFromPoint
答案 0 :(得分:5)
当鼠标悬停在窗口上时,通常不会收到鼠标消息。但是你需要做拖放操作。因此,Windows提供了一种称为鼠标捕获的机制。为防止滥用鼠标,您只能在按下按钮上捕获鼠标。一旦捕获,无论鼠标在屏幕上的什么位置,您都会获得鼠标移动消息,直到您发布捕获或Windows看到相应的按钮消息为止。
这个的C ++代码看起来像这样
case WM_LBUTTONDOWN:
{
SetCapture(hwnd);
}
break;
case WM_MOUSEMOVE:
if (GetCapture() == hwnd)
{
POINT pt = {GET_MOUSE_X(lParam), GET_MOUSE_Y(lParam));
ClientToScreen(hwnd, &pt);
HWND hwndAtPoint = WindowFromPoint(pt);
// Show info for hwndAtPoint....
}
break;
case WM_LBUTTONUP:
if (GetCapture() == hwnd)
{
ReleaseCapture();
}
break;
case WM_CANCELMODE:
// this is a request from Windows that leave my modal state
if (GetCapture() == hwnd)
ReleaseCapture(hwnd);
break;
case WM_CAPTURECHANGED:
// notification that I lost capture (I released it or it was taken from me)
break;
GetAncestor函数可以帮助您从该窗口的窗口转到拥有它的顶级窗口。 GetWindow可用于在窗口树周围走动。
在.NET中,Control类有一个Capture属性,可以看到同样的事情 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.capture.aspx
答案 1 :(得分:2)
您需要先考虑如何在窗口周围绘制矩形,这会影响代码的其余部分。最简单的方法是使用将其TransparencyKey设置为其BackColor和FormBorderStyle设置为None的Form。在Paint事件中绘制一个矩形,其大小与窗体的ClientRectangle相同,可以获得一个可见的矩形,其他一切都是透明的。设置表单的Location和Size属性以匹配您找到的窗口。
现在从鼠标位置找到窗口。您不能使用WindowFromPoint(),它不考虑禁用的窗口。你需要使用EnumWindows()。在回调中,调用GetWindowRect()并检查鼠标是否位于矩形内。一定要忽略你的矩形绘图窗口。
当您获得匹配时,现在使用GW_HWNDPREV重复调用GetWindow()以查找与您找到的窗口重叠的窗口。继续检查矩形并不断忽略矩形窗口。
这最终会让您获得鼠标光标所在的顶级窗口。现在使用ChildWindowFromPoint()来检查鼠标是否在子窗口上(如果有)。如有必要,创建矩形绘图表单,并为其指定与找到的窗口相同的大小和位置。
从显示公牛图形的PictureBox的MouseMove事件中调用此代码。在MouseDown事件中将其Capture属性设置为true。
在MouseUp事件中关闭矩形绘图表单的Close()方法。
答案 2 :(得分:1)
由于您已使用C#对此进行了标记,因此我可以为您正在尝试完成的此项工作添加一两个链接,并希望能够为您提供如何实现此目标的必要信息:
以上所有文章都在CodeProject上。
希望这有帮助, 最好的祝福, 汤姆。
答案 3 :(得分:0)
进口: 使用System.Runtime.InteropServices;
我的建议,当鼠标在你的表单上时,处理鼠标移动/鼠标向上事件(使用Windows钩子捕获表单外的鼠标,看看这里:http://support.microsoft.com/kb/318804),当鼠标释放按钮,在屏幕上获取鼠标位置,并使用您提供的链接获取光标后面的窗口:
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(Point lpPoint);
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out Point lpPoint);
public static IntPtr GetWindowUnderCursor()
{
Point ptCursor = new Point();
if (!(PInvoke.GetCursorPos(out ptCursor)))
return IntPtr.Zero;
return WindowFromPoint(ptCursor);
}
现在你有了窗户把手,从那里可以无穷无尽。
注意:上面的链接(窗口挂钩)只有在窗体上出现鼠标时才会起作用,当鼠标抬起时钩子会结束
答案 4 :(得分:0)
简单。您只需在鼠标按下时设置鼠标捕获,即使它们在您自己的窗口之外,您也可以获得所有鼠标消息。然后在鼠标上,使用WindowFromPoint。
我不熟悉.NET,但使用Win32 API,您可以使用SetCapture设置鼠标捕获。
答案 5 :(得分:0)
您可以查看Winspy++的C ++源代码,这是另一个类似于Winspector Spy的窗口检查程序。不过,我不知道这样的任何开源C#程序。