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 (HDC
s) 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.