Как переместить окно на передний план?
От: Александр Шаргин Россия RSDN.ru
Дата: 15.06.02 22:25
Оценка: 389 (15) +1
Статья:
Как переместить окно на передний план?
Автор(ы): Александр Шаргин


Авторы:
Александр Шаргин

Аннотация:
Многие знают, что для перемещения окна на передний план существует функция SetForegroundWindow из Win32 API (в MFC ей соответствует обёртка CWnd::SetForegroundWindow). Она отлично работала под Windows 95 и Window NT. Но потом парни из Майкрософт провозгласили новый принцип: "Никто кроме пользователя не имеет право выдвигать окно на передний план". И хотя их собственные продукты продолжают делать это при необходимости, функция SetForegroundWindow перестала работать, как раньше. Теперь только активный процесс (foreground process) может переместить окно на передний план с использовании этой функции, а окно фонового процесса начнёт "мерцать" на панели задач, чтобы привлечь внимание пользователя.

В общем случае не рекомендуется нарушать правила работы пользовательского интерфейса, предписанные Микрософт. Как правило, окно, выпрыгивающее из ниоткуда, только раздражает пользователя. Тем не менее, в некоторых приложениях бывает необходимо добиться именно такого поведения. Рассмотрим несколько способов достижения требуемого.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Re[2]: Как переместить окно на передний план?
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 27.01.05 06:56
Оценка: 8 (3)
Здравствуйте, DmitryT, Вы писали:

DT>Особенно, в части перехвата пользовательского ввода функцией AttachThreadInput (подключая свой поток к обработке пользовательского ввода, ты все-таки вмешиваешься в ''нормальную жизнь'' системы).

DT>Не может ли это привести иногда к проблемам в многопоточной программе?

IMHO, все это потеряло актуальность по причине — http://gzip.rsdn.ru/?Forum/Info.aspx?name=FAQ.winapi.wndsetfg
Помещение окна на передний план...
От: Филимонов Илья Вячеславович Россия  
Дата: 16.06.02 22:25
Оценка: 3 (1)
BOOL SetWindowPos(HWND,HWND,int,int,int,int,UINT)
Первый параметр дискриптор окна которое надо переместить на передний план
Второй параметр необходимо установить в HWND_TOP или HWND_TOPMOST
а седьмой в SWP_NOSIZE|SWP_NOMOVE
остальные параметры не имеют значения :)))
Главное — это рабочая концепция и ослиная доля упрямства.
Re: Помещение окна на передний план...
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 16.06.02 23:06
Оценка:
только не "или", а сначала HWND_TOPMOST а потом HWND_TOP. И на передний план оно вылазит, но фокус ввода не получает :(
Re: Помещение окна на передний план...
От: Alexander Shargin Россия RSDN.ru
Дата: 16.06.02 23:59
Оценка:
Можно попробовать после этого сделать окну клик в виде mouse_event или SendInput. Если прокатит, будет ещё один способ в нашей копилке. :)
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Re: Небольшое дополнение
От: SVV Беларусь  
Дата: 11.03.04 15:00
Оценка:
Приведенный код работал у меня не всегда, поэтому я дополнил его и оформил свою функцию:
BOOL    mySetActiveWindow (HWND hWin)
{
  BOOL    rv = FALSE;
  HWND hActiveWin = ::GetForegroundWindow();
  if (hActiveWin==NULL)
    rv = SetForegroundWindow (hWin);
  else
  {
    DR    idMyThread = GetCurrentThreadId();
    DR    idxThread = GetWindowThreadProcessId (hActiveWin, 0);
    if (::AttachThreadInput (idMyThread, idxThread, TRUE))
    {
      if (::ShowWindow(hWin, SW_HIDE))
        if (::ShowWindow(hWin, SW_RESTORE))
          if (SetForegroundWindow (hWin))
          {
            rv = TRUE;
          }
      AttachThreadInput (idMyThread, idxThread, FALSE);
    }
  }
return    rv;
}


главное выделено жирным, без этого подопытное приложение (Calc.Exe, Win2k Sp4 Eng) иногда не хотело выскакивать на верх...
Re[2]: Небольшое дополнение
От: DmitryT  
Дата: 25.01.05 08:34
Оценка:
Здравствуйте, SVV, Вы писали:

SVV>Приведенный код работал у меня не всегда, поэтому я дополнил его и оформил свою функцию:


В каких ситуациях он у тебя не работал?

Есть очень большая программа.
В определенной ситуации она ''выкидывает'' модальный диалог.
Проблема в том, что иногда если юзер не прореагировал на него, через определенное время ''смежники'' выбрасывают
из другого потока еще один модальный диалог.
Так вот после истечения таймаута надо вернуть фокус первому модальному диалогу и закрыть его с возвращением на строку
if (pDlg->DoModal() == IDOK) в коде родителя.

Я применил для этого базовый код Александра Шаргина :
в OnClose() модального диалога при срабатывании таймера:
    if (GetForegroundWindow() != this)
    {
        HWND hCurrWnd;
        int iMyThreadID, iCurrThreadID;

        hCurrWnd = ::GetForegroundWindow();
        iMyThreadID   = GetCurrentThreadId();
        iCurrThreadID = GetWindowThreadProcessId(hCurrWnd, 0);

        AttachThreadInput(iMyThreadID, iCurrThreadID, TRUE);

        SetForegroundWindow();

        AttachThreadInput(iMyThreadID, iCurrThreadID, FALSE);
    }


В 95% случаев работает ''на ура''.
Но иногда обваливается Debug Assertion Failed: file: wincore.cpp line: 4486.
А именно в строчке ASSERT(ContinueModal()):

               // phase2: pump messages while available
                do
                {
                        ASSERT(ContinueModal());
..........................................................

Kaкие будут идеи?
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)
Re[3]: Небольшое дополнение
От: SVV Беларусь  
Дата: 25.01.05 09:33
Оценка:
Здравствуйте, DmitryT, Вы писали:

DT>Здравствуйте, SVV, Вы писали:


SVV>>Приведенный код работал у меня не всегда, поэтому я дополнил его и оформил свою функцию:


DT>В каких ситуациях он у тебя не работал?

есть определенные приложения, написанные фирмой Wincorr Nixdorf...
...
DT>Kaкие будут идеи?
по поводу Assert? никаких идей.
Re[4]: Небольшое дополнение
От: DmitryT  
Дата: 25.01.05 14:34
Оценка:
Поправка: Debug Assertion Failed: file: wincore.cpp line: 3486 (а не 4486).
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)
Re: Как переместить окно на передний план?
От: DmitryT  
Дата: 27.01.05 06:43
Оценка:
Александр Шаргин
Хотелось бы услышать Ваш ''разбор полетов''...
Особенно, в части перехвата пользовательского ввода функцией AttachThreadInput (подключая свой поток к обработке пользовательского ввода, ты все-таки вмешиваешься в ''нормальную жизнь'' системы).
Не может ли это привести иногда к проблемам в многопоточной программе?
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)
Re[3]: Как переместить окно на передний план?
От: DmitryT  
Дата: 27.01.05 09:36
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>IMHO, все это потеряло актуальность по причине — http://gzip.rsdn.ru/?Forum/Info.aspx?name=FAQ.winapi.wndsetfg


Можна развить Вашу мысль?
Почему потеряло актуальность?
Почему
::SendMessage(::GetDesktopWindow(), WM_SYSCOMMAND, (WPARAM) SC_HOTKEY, (LPARAM) hWin);

лучше?
Тем более, мы находимся в той же программв, а не управляем из другой программы...
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)
Re[4]: Как переместить окно на передний план?
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 27.01.05 09:57
Оценка:
Здравствуйте, DmitryT, Вы писали:

DT>Почему потеряло актуальность?

DT>Почему лучше?

все остальные способы, включая тот что с AttachThreadInput() и их комбинации, срабатывают не всегда (результат собственных экспериментов), а этот действует железно.

DT>Тем более, мы находимся в той же программв, а не управляем из другой программы...


результат нестабильный, включая "в той же программе".
Re[5]: Как переместить окно на передний план?
От: DmitryT  
Дата: 27.01.05 11:49
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>все остальные способы, включая тот что с AttachThreadInput() и их комбинации, срабатывают не всегда (результат собственных экспериментов), а этот действует железно.


Но как-то немного ''неловко'' "в той же программе", в том же окне (модальный диалог), посылать себе же
что-то типа:
void C...NumberDlg::OnTimer(UINT nIDEvent) 
{
 ::SendMessage(::GetDesktopWindow(), WM_SYSCOMMAND, (WPARAM) SC_HOTKEY, (LPARAM) this->m_hWnd);
 PostMessage(WM_CLOSE);
 CDialog::OnTimer(nIDEvent);
}

чтобы закрыть его с возвращением на строку if (pDlg->DoModal() == IDOK) в коде родителя.

OE>результат нестабильный, включая "в той же программе".

И в Вашем методе результат нестабильный?
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)
Re[6]: Как переместить окно на передний план?
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 27.01.05 11:51
Оценка:
Здравствуйте, DmitryT, Вы писали:

DT>И в Вашем методе результат нестабильный?


во всех приведенных кроме SC_HOTKEY
Re[3]: Как переместить окно на передний план?
От: DmitryT  
Дата: 01.02.05 09:46
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>IMHO, все это потеряло актуальность по причине — http://gzip.rsdn.ru/?Forum/Info.aspx?name=FAQ.winapi.wndsetfg


Moжешь не поверить, но вариант
::SendMessage(::GetDesktopWindow(), WM_SYSCOMMAND, (WPARAM) SC_HOTKEY, (LPARAM) this->m_hWnd);

у меня вообще не работает...
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)
Re[4]: Как переместить окно на передний план?
От: Аноним  
Дата: 02.07.08 09:46
Оценка:
Здравствуйте, DmitryT, Вы писали:

DT>Moжешь не поверить, но вариант

DT>
DT>::SendMessage(::GetDesktopWindow(), WM_SYSCOMMAND, (WPARAM) SC_HOTKEY, (LPARAM) this->m_hWnd);
DT>

DT>у меня вообще не работает...

А у меня не работает тоже
Re[5]: Как переместить окно на передний план?
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 02.07.08 09:58
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>А у меня не работает тоже


да, отпало, после SP1 кажется
... << RSDN@Home 1.2.0 alpha 4 rev. 1090>>
Re[6]: Как переместить окно на передний план?
От: xmen  
Дата: 22.08.08 22:47
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, <Аноним>, Вы писали:


А>>А у меня не работает тоже


OE>да, отпало, после SP1 кажется


SetForegroundWindow можно разрешить через AllowSetForegroundWindow

Что и демонстрирует мой код:
#define _WIN32_WINNT 0x0500 // Minimum system Windows 2000

bool SetForWindow(HWND hWnd)
{
    if (IsIconic(hWnd))
    {
        ShowWindow(hWnd, SW_RESTORE);
    }

    if (!IsWindowVisible(hWnd))
    {
        ShowWindow(hWnd, SW_SHOW);
    }

    SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0,
                 SWP_NOSIZE | SWP_NOMOVE);
    
    DWORD pId;
    
    if (GetWindowThreadProcessId(hWnd, &pId))
    {
        AllowSetForegroundWindow(pId);
    }
    
    return SetForegroundWindow(hWnd);
}
Re: Как переместить окно на передний план?
От: Eugeny__ Украина  
Дата: 28.01.09 16:53
Оценка:
Здравствуйте, Александр Шаргин, Вы писали:

АШ>Статья:

АШ>Как переместить окно на передний план?
Автор(ы): Александр Шаргин


АШ>Авторы:

АШ> Александр Шаргин

АШ>Аннотация:

АШ>Многие знают, что для перемещения окна на передний план существует функция SetForegroundWindow из Win32 API (в MFC ей соответствует обёртка CWnd::SetForegroundWindow). Она отлично работала под Windows 95 и Window NT. Но потом парни из Майкрософт провозгласили новый принцип: "Никто кроме пользователя не имеет право выдвигать окно на передний план". И хотя их собственные продукты продолжают делать это при необходимости, функция SetForegroundWindow перестала работать, как раньше. Теперь только активный процесс (foreground process) может переместить окно на передний план с использовании этой функции, а окно фонового процесса начнёт "мерцать" на панели задач, чтобы привлечь внимание пользователя.

АШ>В общем случае не рекомендуется нарушать правила работы пользовательского интерфейса, предписанные Микрософт. Как правило, окно, выпрыгивающее из ниоткуда, только раздражает пользователя. Тем не менее, в некоторых приложениях бывает необходимо добиться именно такого поведения. Рассмотрим несколько способов достижения требуемого.


Добрый день всем.

Скажите, а есть решение, которое работает на XP SP3? Сейчас попробывал все те, что указаны в статье — не работают. Самое интересное в третьем случае, SetForegroundWindow просто возвращает ложь, при этом GetLastError возвращает 0...
А нужна программка для переключение приложений, причем висящая как демон, без собственного интерфейса(активизируется по хуку, когда что-то подносят к сканеру штрихкодов, вобщем, не вирусы пишу ).
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Re[2]: Как переместить окно на передний план?
От: YuriKobets Россия http://www.truelaunchbar.com — замена панели быстрого запуска
Дата: 28.01.09 19:42
Оценка:
Здравствуйте, Eugeny__, Вы писали:

E__>Скажите, а есть решение, которое работает на XP SP3? Сейчас попробывал все те, что указаны в статье — не работают. Самое интересное в третьем случае, SetForegroundWindow просто возвращает ложь, при этом GetLastError возвращает 0...

E__>А нужна программка для переключение приложений, причем висящая как демон, без собственного интерфейса(активизируется по хуку, когда что-то подносят к сканеру штрихкодов, вобщем, не вирусы пишу ).


Как вариант можно использовать SwitchToThisWindow. У меня оно точно работает вплоть до висты.
... << RSDN@Home 1.2.0 alpha rev. 676>>
Re[3]: Как переместить окно на передний план?
От: Eugeny__ Украина  
Дата: 29.01.09 10:16
Оценка:
Здравствуйте, YuriKobets, Вы писали:

YK>Здравствуйте, Eugeny__, Вы писали:


E__>>Скажите, а есть решение, которое работает на XP SP3? Сейчас попробывал все те, что указаны в статье — не работают. Самое интересное в третьем случае, SetForegroundWindow просто возвращает ложь, при этом GetLastError возвращает 0...

E__>>А нужна программка для переключение приложений, причем висящая как демон, без собственного интерфейса(активизируется по хуку, когда что-то подносят к сканеру штрихкодов, вобщем, не вирусы пишу ).


YK>Как вариант можно использовать SwitchToThisWindow. У меня оно точно работает вплоть до висты.


Почему-то способ работает только при включенной студии(даже если процесс запускать не из студии). Как только студию выгрузить, на одно из приложений переключается нормально, а вот жавовский фрейм заставляет мигать в трее, а это ну никак не то, что я хотел.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Re[4]: Как переместить окно на передний план?
От: YuriKobets Россия http://www.truelaunchbar.com — замена панели быстрого запуска
Дата: 29.01.09 11:09
Оценка:
Здравствуйте, Eugeny__, Вы писали:

E__>Почему-то способ работает только при включенной студии(даже если процесс запускать не из студии). Как только студию выгрузить, на одно из приложений переключается нормально, а вот жавовский фрейм заставляет мигать в трее, а это ну никак не то, что я хотел.


Может не тот хендл окна передается? Дело в том, что эта функция, походу, используется для Alt+Tab (и раньше была недокументированной). Я ее использую в одном проекте. Нареканий никогда небыло.
... << RSDN@Home 1.2.0 alpha rev. 676>>
Re[5]: Как переместить окно на передний план?
От: Eugeny__ Украина  
Дата: 29.01.09 11:19
Оценка:
Здравствуйте, YuriKobets, Вы писали:

YK>Здравствуйте, Eugeny__, Вы писали:


E__>>Почему-то способ работает только при включенной студии(даже если процесс запускать не из студии). Как только студию выгрузить, на одно из приложений переключается нормально, а вот жавовский фрейм заставляет мигать в трее, а это ну никак не то, что я хотел.


YK>Может не тот хендл окна передается? Дело в том, что эта функция, походу, используется для Alt+Tab (и раньше была недокументированной). Я ее использую в одном проекте. Нареканий никогда небыло.


Хендл тот. При запущенной студии, и тем более, в отладке, все работает как надо. Но как только выгрузишь студию — начинает работать неверно. Бред, блин.
Похоже, винда явовское окно как-то по-другому процессит, попробывал сейчас с другим — все ок. Но мне-то нужно показать жавовское, причем не держать в бекграунде студию при этом.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Re[6]: Как переместить окно на передний план?
От: YuriKobets Россия http://www.truelaunchbar.com — замена панели быстрого запуска
Дата: 29.01.09 12:13
Оценка:
Здравствуйте, Eugeny__, Вы писали:

E__>Хендл тот. При запущенной студии, и тем более, в отладке, все работает как надо. Но как только выгрузишь студию — начинает работать неверно. Бред, блин.

E__>Похоже, винда явовское окно как-то по-другому процессит, попробывал сейчас с другим — все ок. Но мне-то нужно показать жавовское, причем не держать в бекграунде студию при этом.

Может на другой машине попробовать? Может какой-то сторонний софт мешает? Как вариант попробуйте truelaunchbar.com и к ней плугин Windows List. Там как раз эта функция применяется.
... << RSDN@Home 1.2.0 alpha rev. 676>>
Re[7]: Как переместить окно на передний план?
От: Eugeny__ Украина  
Дата: 29.01.09 12:37
Оценка:
Здравствуйте, YuriKobets, Вы писали:

YK>Здравствуйте, Eugeny__, Вы писали:


E__>>Хендл тот. При запущенной студии, и тем более, в отладке, все работает как надо. Но как только выгрузишь студию — начинает работать неверно. Бред, блин.

E__>>Похоже, винда явовское окно как-то по-другому процессит, попробывал сейчас с другим — все ок. Но мне-то нужно показать жавовское, причем не держать в бекграунде студию при этом.

YK>Может на другой машине попробовать? Может какой-то сторонний софт мешает?


Да вроде ничего такого не установлено.

YK>Как вариант попробуйте truelaunchbar.com и к ней плугин Windows List. Там как раз эта функция применяется.


Не, мне оно ничем не поможет. Активно окно1. Мне надо по сигналу от сканера штрихкодов поместить данные в буфер обмена, и показать окно2, а потом через несколько секунд — окно1. При этом пользователь ничего сам делать не должен. Оба окна не принадлежат приложению, которое их должно показывать.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Re[8]: Как переместить окно на передний план?
От: YuriKobets Россия http://www.truelaunchbar.com — замена панели быстрого запуска
Дата: 29.01.09 17:10
Оценка:
Здравствуйте, Eugeny__, Вы писали:

YK>>Как вариант попробуйте truelaunchbar.com и к ней плугин Windows List. Там как раз эта функция применяется.


E__>Не, мне оно ничем не поможет.


Я не ради рекламы, я просто для того что бы проверить, работает оно или нет. Если работает, (я пробовал какое-то ява окно, но не факт, что оно такое же как Ваше), значит, что-то странное с окном или еще с чем в программе. А код что я использую простой до нельзя:
SwitchToThisWindow(m_hWnd, TRUE);
... << RSDN@Home 1.2.0 alpha rev. 676>>
Re[9]: Как переместить окно на передний план?
От: Eugeny__ Украина  
Дата: 30.01.09 09:57
Оценка:
Здравствуйте, YuriKobets, Вы писали:

YK>Здравствуйте, Eugeny__, Вы писали:


YK>>>Как вариант попробуйте truelaunchbar.com и к ней плугин Windows List. Там как раз эта функция применяется.


E__>>Не, мне оно ничем не поможет.


YK>Я не ради рекламы, я просто для того что бы проверить, работает оно или нет. Если работает, (я пробовал какое-то ява окно, но не факт, что оно такое же как Ваше), значит, что-то странное с окном или еще с чем в программе. А код что я использую простой до нельзя:

YK>
YK>SwitchToThisWindow(m_hWnd, TRUE);
YK>


Точно такой же(разве что из шарповского приложения, но не думаю, что это важно). Более того, в отладочном режиме все ок. Ладно, будем копать(но потом, сейчас я под линухом, немного другим занят).
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.