C#WPF SetForegroundWindow(IntPtr hWnd)过度杀伤

时间:2019-01-09 13:41:51

标签: c# wpf window minimize bringtofront

我必须通过自动化启动一个外部程序。 该程序通常具有正常的界面,但是由于我的特殊情况和自动化,将不会显示该程序。 但是,在某些情况下,它将打开一个窗口,并且该窗口必须置于最上方。 因此,情况如下 enter image description here

所以我想要的情况是 enter image description here

而不是 enter image description here

因此,使用我将要描述的代码,该部分可以正常工作。 唯一(主要)问题是,除了打开窗口(此处是消息框)外,还使主程序最小化。这对我来说是个问题。

我不得不说,即使外部程序仅显示1个窗口,子窗口的数量也出乎意料的巨大(例如650)。外部程序是用C ++编写的,对我来说就像一个黑匣子。

因此,代码如下:

[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
public class WindowHandleInfo
{
    private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);

    private IntPtr _MainHandle;

    public WindowHandleInfo(IntPtr handle)
    {
        this._MainHandle = handle;
    }

    public List<IntPtr> GetAllChildHandles()
    {
        List<IntPtr> childHandles = new List<IntPtr>();

        GCHandle gcChildhandlesList = GCHandle.Alloc(childHandles);
        IntPtr pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList);

        try
        {
            EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
            EnumChildWindows(this._MainHandle, childProc, pointerChildHandlesList);
        }
        finally
        {
            gcChildhandlesList.Free();
        }

        return childHandles;
    }

    private bool EnumWindow(IntPtr hWnd, IntPtr lParam)
    {
        GCHandle gcChildhandlesList = GCHandle.FromIntPtr(lParam);

        if (gcChildhandlesList == null || gcChildhandlesList.Target == null)
        {
            return false;
        }

        List<IntPtr> childHandles = gcChildhandlesList.Target as List<IntPtr>;
        childHandles.Add(hWnd);

        return true;
    }
}

public static void BringToFront(string strProcessNameNoExtension)
{
    Process[] anotherApps = Process.GetProcessesByName(strProcessNameNoExtension);
    if (anotherApps.Length == 0) return;
    if (anotherApps[0] != null)
    {
        List<System.IntPtr> allChildWindows = new WindowHandleInfo(anotherApps[0].MainWindowHandle).GetAllChildHandles();
        foreach (var childWindow in allChildWindows)
        {
            SetForegroundWindow(childWindow);
        }
    }
}

因此,简而言之,我找到了所有正在处理的孩子,然后将他们全部带到了前面。 正如我之前所说的,主程序是最小化的。

0 个答案:

没有答案