Возврат в окно, выбранное до щелчка значка в области уведомлений

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

В настоящее время я использую this.Hide() для удаления формы (либо когда происходит желаемое событие в форме, либо когда форма имеет значение Deactivated), но когда я это делаю, Windows устанавливает фокус пользователя на панель задач. Как я могу заставить его вернуть фокус пользователей в то окно, в котором они находятся, прежде чем щелкнуть значок области уведомлений?


person topherg    schedule 16.04.2013    source источник


Ответы (2)


Мне удалось выяснить, как это сделать. Я использовал следующий код:

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hwnd);

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr GetWindow(IntPtr hwnd, int wFlag);

private void switchToLast() {
    IntPtr thisWindow = GetForegroundWindow();
    IntPtr lastWindow = GetWindow(thisWindow, 3);
    SetForegroundWindow(lastWindow);
    this.Hide();
}

Я нашел многочисленные ссылки на проблему, и это то, что у меня есть до сих пор. Основное различие между этим и другими примерами, которые я нашел, - это строка GetWindow(thisWindow, 3), где второй был 2 в других примерах, я изменил это на 3. Я считаю, что это потому, что установка этого значения 2 приводила к получению указателя на TaskBar.

person topherg    schedule 17.04.2013
comment
Не совсем уверен, как это могло работать. Подходящим способом является получение дескриптора окна до отображения формы. В этом случае 2 (GW_HWNDNEXT) будет правильным выбором. - person Hans Passant; 17.04.2013

Вместо того, чтобы пытаться выяснить это постфактум, вы должны определить это с самого начала, когда ваше приложение впервые получает фокус. Другими словами, чем раньше вы это разберетесь, тем лучше.

Очевидным решением будет обработка сообщений WM_SETFOCUS или WM_ACTIVATE, которые передают дескриптор ранее активному окну как lParam. К сожалению, это работает только для окон в одном потоке; в противном случае lParam будет NULL.

Поэтому вам нужно использовать WM_ACTIVATEAPP, который передает идентификатор потока, который владеет деактивируемым окном как lParam. Получив идентификатор потока, используйте функцию GetGUIThreadInfo, чтобы определить активное окно в эта нить. Это работает независимо от того, какой процесс владеет окном, поэтому на него не распространяются ограничения, описанные выше для WM_SETFOCUS и WM_ACTIVATE.

Следите за этим дескриптором окна и просто верните ему фокус, когда закончите.

person Cody Gray    schedule 17.04.2013