获取子 window 的句柄以在 C# 中发布消息

Get handle of child window to postmessage in C#

我正在寻找如何获取子 window 的句柄并在那里发送消息。

我的代码:

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        //This send postmessage to window "192.168.0.94 - Remote Desktop Connection"//
        IntPtr hwnd10 = FindWindow(null, "192.168.0.94 - Remote Desktop Connection");
        Point location = new Point(636, 324);
        PostMessage(hwnd10, WM_MOUSEMOVE, 0, MAKELPARAM(location.X, location.Y));
        PostMessage(hwnd10, WM_LBUTTONDOWN, 0x1, MAKELPARAM(location.X, location.Y));
        PostMessage(hwnd10, WM_LBUTTONUP, 0, MAKELPARAM(location.X, location.Y));

        // But now how can i do the same to child window "Input Capture Window"?

我做了一些研究,我发现 [pageenumchildwindows][1] 但我不知道如何在我的示例中使用它。

截图看看 window 我到底在找什么 :

好的,感谢 Oguz Ozgul,我找到了解决方案。 我是通过 FindWindowEx 完成的,比如 :

 IntPtr child = FindWindowEx(hwnd10, IntPtr.Zero, "TscShellAxHostClass", null);
        //check if window is caught
        if(child!=IntPtr.Zero)
        {
            Console.WriteLine("Findow TscShellAxHostClass found!!!");

            child = FindWindowEx(child, IntPtr.Zero, "ATL:00007FFC92EAF400", null);
            if (child != IntPtr.Zero)
            {
                Console.WriteLine("Findow ATL:00007FFC92EAF400 found!!!");

                child = FindWindowEx(child, IntPtr.Zero, "UIMainClass", null);
                if (child != IntPtr.Zero)
                {

                    Console.WriteLine("Findow UIMainClass found!!!");
                    child = FindWindowEx(child, IntPtr.Zero, "UIContainerClass", null);
                    if (child != IntPtr.Zero)
                    {

                        Console.WriteLine("Findow UIContainerClass found!!!");
                        child = FindWindowEx(child, IntPtr.Zero, "IHWindowClass", null);
                        if (child != IntPtr.Zero)
                        {
                            Console.WriteLine("Findow IHWindowClass found!!!");
                        }
                    }
                }
            }
        }

这是另一个实现,使用 EnumWindowsEnumChildWindows

这个答案并不意味着要被标记,而是展示了解决同一问题的不同方法。

搜索深度为3,可以在代码中增加,甚至可以作为构造函数或方法参数获取。

有效。

public class RecursiveWindowSearcher
{
    public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
    [DllImport("user32")]
    public extern static int EnumWindows(EnumWindowsProc lpEnumFunc, int lParam);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

    private IntPtr windowParent;
    private string windowName;
    private IntPtr windowPointer;

    public RecursiveWindowSearcher(string windowName, IntPtr windowParent)
    {
        this.windowName = windowName;
        this.windowParent = windowParent;
    }

    public bool WinApiCallback(IntPtr hwnd, IntPtr lParam)
    {
        Console.WriteLine("Window: {0}", hwnd);

        StringBuilder windowNameFar = new StringBuilder(256);
        GetWindowText(hwnd, windowNameFar, 256);

        if (windowNameFar.ToString() == windowName)
        {
            windowPointer = hwnd;
            return false;
        }   

        Console.WriteLine("Name: {0}", windowNameFar);

        if(indent == 6)
        {
            return false;
        }
        indent += 2;
        EnumChildWindows(hwnd, WinApiCallback, IntPtr.Zero);
        indent -= 2;

        return true;
    }

    public IntPtr Find()
    {
        this.windowPointer = IntPtr.Zero;
        if (windowParent == IntPtr.Zero)
        {
            EnumWindows(WinApiCallback, 0);
        }
        else
        {
            EnumChildWindows(windowParent, WinApiCallback, IntPtr.Zero);
        }
        return windowPointer;
    }
}

而且用法很简单:

第二个构造函数参数是指向现有 window 的指针,从中开始搜索。如果您有此句柄,则可以传递它以将搜索范围缩小到特定的 window 及其子项。

static void Main()
{
    IntPtr windowFound = new RecursiveWindowSearcher("Skype for Business ", IntPtr.Zero).Find();
    Console.ReadLine();
}