-2

I'm using Easy Hook lib. How get owner window handle?

    [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 and other are no working, too how to get the parent window ?

1 Answers1

0
var parent = GetAncestor(hDc, GetAncestorFlags.GetParent); // always return 0! why????????????????

This code is completely wrong. The only reason you are able to compile it is because both HWND and HDC are typed as pointers (IntPtr) in a managed environment. If you were writing in C or C++, you would get a compilation error, making the problem easier to see.

The DrawText function, which you have hooked, has as its first parameter a handle to the device context (HDC) on which the text is to be drawn.

The GetAncestor function, which you are calling, has as its first parameter a handle to a window (HWND). HDC and HWND are incompatible types; they cannot be interchanged.

Device contexts (HDCs) do not have "ancestors", and even if they did, the GetAncestor function is designed only for windows. It has no idea what to do with a device context, so it fails. You've passed it an invalid window handle.

As far as your actual question, of how to get the "parent window" corresponding to a DC, this question does not make any sense. Device contexts do not have "parent" windows, and only some device contexts are even associated with a window. If a device context is associated with a window, you can call the WindowFromDC function, passing in the HDC to retrieve the associated HWND. Again, I must emphasize that this will not solve your actual problem. A device context is not guaranteed to be associated with a window. The device context might be associated with the screen, or it might be a memory DC, or it might be a device DC (associated with a physical monitor, a printer, or other output device). In all of these cases, WindowFromDC will return NULL (a null pointer, or the value IntPtr.Zero).

If you think about this logically, you'll see where what you are asking falls apart. Consider the simple case where the application creates a memory DC and calls DrawText to draw text into it. What "window" would you want to retrieve? Maybe the "main" window for the process? First off, there's no way to determine that for an arbitrary process. Second, the process may not even have any windows! I can create a windowless process that creates and draws text into memory DCs. If I do so, it had better not crash your hook!

You've resisted several pleas in the comments to explain what the purpose of this code is. It is still not clear why you are hooking DrawText in the first place. Your hook procedure does not do anything useful. Also, you miss the case where the application calls DrawTextEx, ExtTextOut, or TextOut to draw text, and that's assuming that it even uses GDI to draw text. If it uses GDI+, DirectDraw, or some other drawing API, your hook will never be called. The only reason to hook calls to DrawText would be if you want to change its behavior. You aren't actually changing the behavior in your hook procedure, and it is neither possible nor sensible to change its behavior based on a window. It is a drawing function that deals only with device contexts.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • I have questions of the . We have a lot of windows application. Each window has its own configuration. I need to change the text in the control , depending on the window . How to get access to these controls? spy ++ does not see them (they have no window ) using C# – Владимир Хилько Sep 07 '16 at 12:29
  • You will need to dig out your applications's source code then, or hope that [System.Windows.Automation](https://msdn.microsoft.com/en-us/library/ms747327(v=vs.110).aspx) can see the controls or let you change the text. Or if the strings come from a strings table resource, use a resource editor. Good luck. – andlabs Sep 07 '16 at 20:21