我正在使用Easy Hook lib。如何获得所有者窗口?
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public override string ToString()
{
return $"[Left: {Left}, Top: {Top}, Right: {Right}, Bottom: {Bottom}]";
}
}
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int DrawText(IntPtr hDc, string lpString, int nCount, ref Rect lpRect, uint uFormat);
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
public delegate int DDrawText(IntPtr hDc, string lpString, int nCount, ref Rect lpRect, uint uFormat);
private int DrawText_Hooked(IntPtr hDc, string lpString, int nCount, ref Rect lpRect, uint uFormat)
{
var This = (Main) HookRuntimeInfo.Callback;
lock (This._queue)
{
var parent = GetAncestor(hDc, GetAncestorFlags.GetParent); // always return 0! why????????????????
This._queue.Push($"parent [{parent}]");
}
return DrawText(hDc, lpString, nCount, ref lpRect, uFormat);
}
GetWindowDC,GetDC,GetParent等也不起作用 如何获取父窗口?
答案 0 :(得分:0)
var parent = GetAncestor(hDc, GetAncestorFlags.GetParent); // always return 0! why????????????????
此代码完全错误。您能够编译它的唯一原因是因为HWND
和HDC
在托管环境中都被键入为指针(IntPtr
)。如果您使用C或C ++编写,则会出现编译错误,使问题更容易看到。
您已挂钩的DrawText
函数的第一个参数是设备上下文(HDC
)的句柄,用于绘制文本。
您正在调用的GetAncestor
函数的第一个参数是窗口句柄(HWND
)。 HDC
和HWND
是不兼容的类型;他们不能互换。
设备上下文(HDC
s)没有“祖先”,即使他们这样做,GetAncestor
函数也仅适用于Windows。它不知道如何处理设备上下文,因此它失败了。你已经传递了一个无效的窗口句柄。
就你的实际问题而言,如何获得与DC相对应的“父窗口”,这个问题没有任何意义。设备上下文没有“父”窗口,只有某些设备上下文甚至与窗口关联。 如果设备上下文与窗口关联,您可以调用WindowFromDC
function,传入HDC
以检索关联的HWND
。同样,我必须强调,这不会解决你的实际问题。 不保证设备上下文与窗口关联。设备上下文可能与屏幕关联,或者可能是内存DC,或者它可能是设备DC(与物理相关联)监视器,打印机或其他输出设备)。在所有这些情况下,WindowFromDC
将返回NULL
(空指针或值IntPtr.Zero
)。
如果你从逻辑上考虑这个问题,你会发现你所要求的地方分崩离析。考虑应用程序创建内存DC并调用DrawText
以将文本绘制到其中的简单情况。你想要检索什么“窗口”?也许这个过程的“主要”窗口?首先,没有办法确定任意过程。其次,该过程可能甚至没有拥有任何窗口!我可以创建一个无窗口进程,创建并将文本绘制到内存DC中。如果我这样做,最好不要让你的钩子崩溃!
您在评论中拒绝了几个请求,以解释此代码的目的是什么。目前还不清楚为什么要首先挂钩DrawText
。你的钩子程序没有做任何有用的事情。此外,您错过了应用程序调用{{1}},DrawTextEx
或ExtTextOut
来绘制文本的情况,并且假设它甚至使用GDI绘制文本。如果它使用GDI +,DirectDraw或其他一些绘图API,则永远不会调用您的钩子。将调用挂接到TextOut
的唯一原因是,如果要更改其行为。实际上,您并没有更改钩子过程中的行为,并且基于窗口更改其行为既不可能也不明智。它是一个只处理设备上下文的绘图函数。