TopMost не всегда TopMost - WPF - PullRequest
       2

TopMost не всегда TopMost - WPF

3 голосов
/ 16 сентября 2010

У меня есть приложение с часами. Я установил свойство TopMost окна. Но, случайно, какое-то другое окно или визуальная студия выходят за пределы часов.

Есть ли другой способ заставить мое окно (приложение часов) отображаться всегда поверх всех других приложений.

Ответы [ 3 ]

17 голосов
/ 13 января 2014

Я знаю, что этот вопрос старый, но я не совсем понимаю, почему принятый ответ получил голоса ... или почему он был принят ... он не действительно отвечает на вопрос или предоставить решение и ответы, опубликованные в эти дни, которые так коротки, почти всегда отклоняются , проголосованными и / или удаленными сообществом. Ах, ну, я думаю, это было опубликовано в разное время.

В любом случае, как бы ни стара, у меня есть возможное решение для любого, кто может столкнуться с этим постом в будущем. Вы можете просто обработать Window.Deactivated событие и / или Application.Deactivated событие . Window.Deactivated Событие происходит, когда окно становится фоновым окном , а Application.Deactivated Событие происходит, когда приложение перестает быть приложением переднего плана .

Идея состоит в том, чтобы установить соответствующее свойство TopMost равным true каждый раз, когда ваше приложение или Window теряет фокус:

private void Window_Deactivated(object sender, EventArgs e)
{
    // The Window was deactivated 
    this.TopMost = true;
}

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

1 голос
/ 22 февраля 2017

У меня также была эта проблема, когда установка Window.Topmost = true в уже существующем окне иногда работала, иногда нет. Ниже мой обходной путь, вы, вероятно, можете объединить его с подходом Window_Deactivation, упомянутым другими, если стиль WS_EX_TOPMOST потерян во время выполнения.

App.Current.MainWindow.Topmost = true;

// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(App.Current.MainWindow).Handle;

// Intentionally do not await the result
App.Current.Dispatcher.BeginInvoke(new Action(async () => await RetrySetTopMost(hwnd)));

Дополнительный код:

private const int RetrySetTopMostDelay = 200;
private const int RetrySetTopMostMax = 20;

// The code below will retry several times before giving up. This always worked with one retry in my tests.
private static async Task RetrySetTopMost(IntPtr hwnd)
{
    for (int i = 0; i < RetrySetTopMostMax; i++)
    { 
        await Task.Delay(RetrySetTopMostDelay);
        int winStyle = GetWindowLong(hwnd, GWL_EXSTYLE);

        if ((winStyle & WS_EX_TOPMOST) != 0)
        {
            break;
        }

        App.Current.MainWindow.Topmost = false;
        App.Current.MainWindow.Topmost = true;
    }
}

internal const int GWL_EXSTYLE = -20;
internal const int WS_EX_TOPMOST = 0x00000008;

[DllImport("user32.dll")]
internal static extern int GetWindowLong(IntPtr hwnd, int index);
0 голосов
/ 16 сентября 2010

Вы уверены, что это случайное окно?Если другое окно также является верхним, оно может оказаться выше вашего окна.

...