C# 如何从另一个进程而不是子控件获取子窗口?

C# 如何从另一个进程而不是子控件获取子窗口?,c#,user32,interopservices,C#,User32,Interopservices,我的任务是找到一种方法,使另一个应用程序显示在其他窗口的顶部(始终在顶部)。我可以使用RetrieveProcesses()函数获取具有窗口标题的进程。一旦用户选择要修改的进程,我的应用程序将调用MakeProcessOnTop或MakeProcessNormal。这两个函数都修改主应用程序的窗口。在我添加修改其子项之前,这是正确的 然后我发现这在子窗口上不起作用(就像outlook中的电子邮件),所以我开始寻找处理子窗口的方法。以下代码的编写方式最终会弄乱子窗口。如何获取子窗口而不是子控件的句

我的任务是找到一种方法,使另一个应用程序显示在其他窗口的顶部(始终在顶部)。我可以使用RetrieveProcesses()函数获取具有窗口标题的进程。一旦用户选择要修改的进程,我的应用程序将调用MakeProcessOnTop或MakeProcessNormal。这两个函数都修改主应用程序的窗口。在我添加修改其子项之前,这是正确的

然后我发现这在子窗口上不起作用(就像outlook中的电子邮件),所以我开始寻找处理子窗口的方法。以下代码的编写方式最终会弄乱子窗口。如何获取子窗口而不是子控件的句柄指针

public static class ProcessManagement
{
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr SetFocus(IntPtr hWnd);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);

    static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
    static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
    static readonly IntPtr HWND_TOP = new IntPtr(0);
    static readonly IntPtr HWND_BOTTOM = new IntPtr(1);

    public static IEnumerable<Process> RetrieveProcesses()
    {
        List<Process> returnList = new List<Process>();

        Process[] processArray = Process.GetProcesses();

        foreach (Process p in processArray)
        {
            if (!String.IsNullOrEmpty(p.MainWindowTitle))
            {
                returnList.Add(p);
            }
        }

        return returnList;
    }

    public static IntPtr GetProcessWindowHandle(int processId)
    {
        Process p = Process.GetProcessById(processId: processId);
        return p.MainWindowHandle;
    }

    public static List<IntPtr> GetProcessChildWindowHandles(IntPtr parent)
    {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try
        {
            EnumWindowsProc childProc = new EnumWindowsProc(EnumWindow);
            EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
        }
        finally
        {
            if (listHandle.IsAllocated)
                listHandle.Free();
        }
        return result;
    }

    private static bool EnumWindow(IntPtr handle, IntPtr pointer)
    {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
        {
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
        }
        list.Add(handle);
        //  You can modify this to check to see if you want to cancel the operation, then return a null here
        return true;
    }

    public static bool MakeProcessOnTop(IntPtr targetWindowHandle, bool targetChildren = true)
    {
        bool bReturn = true;

        if (!ShowWindow(targetWindowHandle, ShowWindowCommands.Minimize))
        {
            bReturn = false;
        }

        if (!ShowWindow(targetWindowHandle, ShowWindowCommands.Restore))
        {
            bReturn = false;
        }

        if (!ShowWindow(targetWindowHandle, ShowWindowCommands.ShowNoActivate))
        {
            bReturn = false;
        }

        if (!SetWindowPos(targetWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE))
        {
            bReturn = false;
        }

        if (targetChildren)
        {
            List<IntPtr> childProcesses = GetProcessChildWindowHandles(targetWindowHandle);

            foreach(IntPtr iPtr in childProcesses)
            {
                MakeProcessOnTop(iPtr, false);
            }
        }

        return bReturn;
    }
    public static bool MakeProcessNormal(IntPtr targetWindowHandle, bool targetChildren = true)
    {
        bool bReturn = true;

        if (!ShowWindow(targetWindowHandle, ShowWindowCommands.Minimize))
        {
            bReturn = false;
        }

        if (!ShowWindow(targetWindowHandle, ShowWindowCommands.Restore))
        {
            bReturn = false;
        }

        if (!ShowWindow(targetWindowHandle, ShowWindowCommands.ShowNoActivate))
        {
            bReturn = false;
        }

        if (!SetWindowPos(targetWindowHandle, HWND_NOTOPMOST, 0, 0, 0, 0, SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE))
        {
            bReturn = false;
        }

        if (targetChildren)
        {
            List<IntPtr> childProcesses = GetProcessChildWindowHandles(targetWindowHandle);

            foreach (IntPtr iPtr in childProcesses)
            {
                MakeProcessNormal(iPtr, false);
            }
        }

        return bReturn;
    }
}
公共静态类进程管理
{
[DllImport(“user32.dll”,SetLastError=true)]
静态外部bool SetWindowPos(IntPtr hWnd、IntPtr hwninsertafter、intx、inty、intcx、intcy、SetWindowPosFlags uFlags);
[DllImport(“user32.dll”,SetLastError=true)]
静态外部IntPtr SetFocus(IntPtr hWnd);
[DllImport(“user32.dll”)]
[返回:Marshallas(UnmanagedType.Bool)]
静态外部bool ShowWindow(IntPtr hWnd、ShowWindowCommands nCmdShow);
[DllImport(“user32.dll”)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部bool EnumChildWindows(IntPtr hwndpresent、EnumWindowsProc lpEnumFunc、IntPtr lParam);
静态只读IntPtr HWND_TOPMOST=新IntPtr(-1);
静态只读IntPtr HWND_NOTOPMOST=新的IntPtr(-2);
静态只读IntPtr HWND_TOP=新IntPtr(0);
静态只读IntPtr HWND_BOTTOM=新IntPtr(1);
公共静态IEnumerable RetrieveProcess()
{
List returnList=新列表();
Process[]processArray=Process.getprocesss();
foreach(processArray中的进程p)
{
如果(!String.IsNullOrEmpty(p.MainWindowTitle))
{
返回列表。添加(p);
}
}
退货清单;
}
公共静态IntPtr GetProcessWindowHandle(int processId)
{
processp=Process.GetProcessById(processId:processId);
返回p.main窗口句柄;
}
公共静态列表GetProcessChildWindowHandles(IntPtr父级)
{
列表结果=新列表();
GCHandle listHandle=GCHandle.Alloc(结果);
尝试
{
EnumWindowsProc childProc=新的EnumWindowsProc(EnumWindow);
EnumChildWindows(父、childProc、GCHandle.ToIntPtr(listHandle));
}
最后
{
if(listHandle.IsAllocated)
Free();
}
返回结果;
}
私有静态布尔枚举窗口(IntPtr句柄、IntPtr指针)
{
GCHandle gch=GCHandle.FromIntPtr(指针);
列表=gch。目标为列表;
if(list==null)
{
抛出新的InvalidCastException(“GCHandle目标无法强制转换为列表”);
}
列表。添加(句柄);
//您可以对此进行修改以检查是否要取消该操作,然后在此处返回null
返回true;
}
公共静态bool MakeProcessOnTop(IntPtr targetWindowHandle,bool targetChildren=true)
{
bool-bReturn=true;
如果(!ShowWindow(targetWindowHandle,ShowWindowCommands.Minimize))
{
bReturn=false;
}
如果(!ShowWindow(targetWindowHandle,ShowWindowCommands.Restore))
{
bReturn=false;
}
如果(!ShowWindow(targetWindowWhandle、ShowWindowCommands.ShowNoActivate))
{
bReturn=false;
}
如果(!SetWindowPos(targetWindowWhandle,HWND_TOPMOST,0,0,0,SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE))
{
bReturn=false;
}
if(目标儿童)
{
List childProcesses=GetProcessChildWindowHandles(targetWindowHandle);
foreach(子进程中的IntPtr iPtr)
{
MakeProcessOnTop(iPtr,false);
}
}
回程;
}
公共静态bool MakeProcessNormal(IntPtr targetWindowHandle,bool targetChildren=true)
{
bool-bReturn=true;
如果(!ShowWindow(targetWindowHandle,ShowWindowCommands.Minimize))
{
bReturn=false;
}
如果(!ShowWindow(targetWindowHandle,ShowWindowCommands.Restore))
{
bReturn=false;
}
如果(!ShowWindow(targetWindowWhandle、ShowWindowCommands.ShowNoActivate))
{
bReturn=false;
}
如果(!SetWindowPos(targetWindowWhandle,HWND_NOTOPMOST,0,0,0,SetWindowPosFlags.SWP_noactive | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE))
{
bReturn=false;
}
if(目标儿童)
{
List childProcesses=GetProcessChildWindowHandles(targetWindowHandle);
foreach(子进程中的IntPtr iPtr)
{
MakeProcessNormal(iPtr,false);
}
}
回程;
}
}

始终在顶部仅对顶级窗口或可能的MDI子窗口有意义


您可以通过操纵Z顺序来提升子窗口,但没有明确定义如何将其放回原位。

始终在顶部仅对顶级窗口或可能的MDI子窗口有意义


您可以通过操纵Z顺序来引发子窗口,但它没有很好地定义如何将其放回。

您查看过这些帖子吗?我尝试过EnumThreadWindows,但没有成功。您查看过这些帖子吗?我尝试过EnumThreadWindows,但没有成功。我也尝试过使用EnumThreadWindows,因此我将假设我尝试做的事情没有得到很好的支持,可能没有意义。我尝试也使用EnumThreadWindows,但没有成功,所以我