-2

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 なども機能しません。親ウィンドウを取得する方法は?

4

1 に答える 1

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

このコードは完全に間違っています。コンパイルできる唯一の理由は、管理された環境でHWNDとの両方HDCがポインター ( ) として型指定されているためです。IntPtrC または C++ で記述している場合は、コンパイル エラーが発生し、問題が分かりやすくなります。

フックした関数には、最初のパラメーターとして、テキストが描画されるDrawTextデバイス コンテキスト ( ) へのハンドルがあります。HDC

GetAncestor呼び出している関数には、最初のパラメーターとしてウィンドウへのハンドル ( )がありHWNDます。互換性のないタイプですHDCHWNDそれらを交換することはできません。

デバイス コンテキスト ( HDCs) には "祖先" がありません。たとえあったとしても、GetAncestor関数はウィンドウ専用に設計されています。デバイス コンテキストで何をすべきかわからないため、失敗します。無効なウィンドウ ハンドルを渡しました。

DCに対応する「親ウィンドウ」を取得する方法についての実際の質問に関しては、この質問は意味がありません。デバイス コンテキストには「親」ウィンドウがなく、一部のデバイス コンテキストのみがウィンドウに関連付けられています。デバイス コンテキストがウィンドウに関連付けられている場合は、関数 を呼び出してWindowFromDC渡しHDC関連付けられている を取得できますHWND。繰り返しますが、これは実際の問題を解決しないことを強調しなければなりません。デバイス コンテキストがウィンドウに関連付けられているとは限りません。デバイス コンテキストは、画面に関連付けられているか、メモリ DC であるか、デバイス DC (物理モニター、プリンター、またはその他の出力デバイスに関連付けられている) である可能性があります。これらすべての場合において、WindowFromDCNULL(null ポインター、または value )を返しますIntPtr.Zero

これを論理的に考えると、求めていることがどこで崩れるかがわかります。アプリケーションがメモリ DC を作成し、そこにDrawTextテキストを描画するために呼び出しを行う単純なケースを考えてみましょう。どの「ウィンドウ」を取得しますか? たぶん、プロセスの「メイン」ウィンドウですか?まず、任意のプロセスでそれを判断する方法はありません。第二に、プロセスにはウィンドウさえないかもしれません! テキストを作成してメモリ DC に描画するウィンドウレス プロセスを作成できます。私がそうするなら、あなたのフックをクラッシュさせないほうがいいです!

あなたは、このコードの目的を説明するようコメントでいくつかの嘆願に抵抗しました。そもそもなぜあなたがフックしているのかはまだ明らかではありませんDrawText。フック プロシージャは何も役に立ちません。DrawTextExまた、アプリケーションが、ExtTextOut、またはを呼び出してテキストを描画するケースを見逃していTextOutます。これは、GDI を使用してテキストを描画することも想定しています。GDI+、DirectDraw、またはその他の描画 API を使用する場合、フックは呼び出されません。呼び出しをフックする唯一の理由はDrawText、その動作を変更したい場合です。実際にフック プロシージャの動作を変更しているわけではなく、ウィンドウに基づいてその動作を変更することは不可能であり、賢明でもありません。デバイスコンテキストのみを扱う描画機能です。

于 2016-09-07T10:22:34.877 に答える