Перевести другое окно процессов на передний план, когда оно имеет ShowInTaskbar = false

Мы хотим, чтобы только один экземпляр нашего приложения работал одновременно. Поэтому при запуске он проверяет, запущено ли приложение и вызывает ли оно SetForegroundWindow в главном окне.

Это все хорошо и хорошо... по большей части..

Когда наше приложение запустится, оно покажет экран-заставку и форму входа. Обе эти формы имеют ShowInTaskBar = false.

Из-за этого, если вы попытаетесь запустить другую копию приложения, когда отображается форма входа в систему, эта форма входа не выводится на передний план!

Тем более, что пользователь не видит ничего и на панели задач, все, что они считают, это то, что приложение не работает и не может запуститься. Нет никаких признаков того, что запущен другой экземпляр.

Есть ли способ обойти эту проблему?

3 ответа

Решение

Ну, код здесь. Даже если ShowInTaskBar является false, вы должны быть в состоянии вывести его на фронт.

    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);

    [DllImport("USER32.DLL")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    public static void bringToFront(string title) {
        // Get a handle to the Calculator application.
        IntPtr handle = FindWindow(null, title);

        // Verify that Calculator is a running process.
        if (handle == IntPtr.Zero) {
            return;
        }

        // Make Calculator the foreground application
        SetForegroundWindow(handle);
    }

Примечание: вы должны FindWindow используя класс формы, а не по имени, так как формы заставки иногда не имеют заголовков или даже элемента управления. Используйте Spy++, чтобы копать глубже.

использование FindWindow на всплеск. Я думаю, что это то, что вы хотите сделать - вывести заставку впереди при загрузке основной формы.

Я думаю, что это лучшее решение, потому что оно восстанавливается из минимизированного состояния:

public static class WindowHelper
{
    public static void BringProcessToFront(Process process)
    {
        IntPtr handle = process.MainWindowHandle;
        if (IsIconic(handle))
        {
            ShowWindow(handle, SW_RESTORE);
        }

        SetForegroundWindow(handle);
    }

    const int SW_RESTORE = 9;

    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool SetForegroundWindow(IntPtr handle);
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool IsIconic(IntPtr handle);
}

Простой звонок:

WindowHelper.BringProcessToFront(process);
FindWindow(null, title);

Найдет первое окно, которое соответствует запросу. Это может привести к неожиданному поведению, если другое окно использует тот же заголовок.

Хотя шансы на это могут казаться редкими или невозможными (одно приложение), это может легко произойти. Например, проводник Windows использует имя выбранного каталога в качестве заголовка окна (хотя оно и невидимо). Теперь, если заголовок окна является общим термином или совпадает с именем каталога приложения, это может быть проблемой.

Другие вопросы по тегам