C # WPF Превышение SetForegroundWindow (IntPtr hWnd) - PullRequest
0 голосов
/ 09 января 2019

Мне нужно запустить внешнюю программу через автоматизацию. Эта программа обычно имеет нормальный интерфейс, но из-за моего специфического случая и из-за автоматизации она не будет показана. Однако в некоторых случаях это откроет окно, и это окно должно быть расположено сверху. Таким образом, ситуация ниже 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);
        }
    }
}

Короче говоря, я нахожу всех детей в процессе, а затем вывожу их всех вперед. Как я уже говорил, основная программа минимизирована.

...