在DrawText钩子中从child获取Parent Hwd
本文关键字:child 获取 Parent Hwd DrawText | 更新日期: 2023-09-27 18:05:41
我使用Easy Hook库。如何获得所有者窗口句柄?
[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);
}
gettwindowdc, GetDC, GetParent和其他也不起作用如何获取父窗口
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
函数,传入HDC
来检索相关的HWND
。我必须再次强调,这并不能解决你的实际问题。设备上下文不能保证与窗口相关联。设备上下文可能与屏幕相关联,也可能是内存DC,也可能是设备DC(与物理监视器、打印机或其他输出设备相关联)。在所有这些情况下,WindowFromDC
将返回NULL
(一个空指针,或者值IntPtr.Zero
)。
如果你从逻辑上思考这个问题,你就会发现你的问题在哪里出错了。考虑这样一个简单的情况:应用程序创建一个内存DC,并调用DrawText
向其中绘制文本。您想要检索哪个"窗口"?也许是流程的"主"窗口?首先,对于任意的过程,没有办法确定这一点。第二,进程甚至可能没有有任何窗口!我可以创建一个无窗口进程来创建文本并将其绘制到内存dc中。如果我这样做,它最好不要撞坏你的钩子!
您在评论中多次拒绝解释这段代码的目的是什么。现在还不清楚为什么要钩住DrawText
。钩子子程没有做任何有用的事情。此外,您还忽略了应用程序调用DrawTextEx
、ExtTextOut
或TextOut
来绘制文本的情况,这是假设它甚至使用GDI来绘制文本。如果它使用GDI+、DirectDraw或其他绘图API,你的钩子将永远不会被调用。钩子调用DrawText
的唯一原因是如果你想改变它的行为。你实际上并没有改变钩子子程的行为,基于一个窗口改变钩子子程的行为既不可能也不明智。它是一个绘图函数,只处理设备上下文。