Переместить окно поверх других.
От: Went  
Дата: 02.11.16 14:33
Оценка:
Здравствуйте. Есть окно, чей хэндл мне известен. В общем случае оно может принадлежать другому процессу. Необходимо переместить окно поверх других (результат, аналогичный Alt + Tab-у на иконку данного приложения). Не могу подобрать WIN API функцию, которая бы дала нужный результат. Варианты, которые я попробовал:

1. ShowWindow(hwnd, SW_RESTORE);
Это работает для случая, если окно свернуто, для окна, которое накрыто другим окном, ничего не происходит по-моему.

2. SetForegroundWindow(hwnd);
Это работает почти всегда, кроме одного важного случая. У меня два инстанса одного приложения — два одинаковых окна накладываются точно одно поверх другого. Если нижнее приложение пытается "всплыть" при помощи этой функции, таскбар активируется, нужное приложение становится "синим" (ну, якобы получает фокус), но само окно остается накрытым старым окном.

3. BringWindowToTop(hwnd);
Вообще ничего не делает.

Как быть? Есть какой-то надежный способ "поднять" окно?
Re: Переместить окно поверх других.
От: GlebZ Россия  
Дата: 02.11.16 14:40
Оценка:
Здравствуйте, Went, Вы писали:

W>Как быть? Есть какой-то надежный способ "поднять" окно?

Если ты сам в foreground, тогда чтобы более менее гарантированно необходимо вызвать AllowSetForegroundWindow на процесс. А дальше пусть он дальше кувыркается. Остальные способы более похожи на танцы с бубном.
Re: Переместить окно поверх других.
От: Carc Россия https://vk.com/gosha_mazov
Дата: 02.11.16 15:08
Оценка:
Здравствуйте, Went, Вы писали:

W>Как быть? Есть какой-то надежный способ "поднять" окно?
Можно прицепить к вводу foreground-окна, используя AttachThreadInput и только потом всплывать через SetForegroundWindows.
Aml Pages Home
Re[2]: Переместить окно поверх других.
От: Went  
Дата: 02.11.16 15:08
Оценка:
Здравствуйте, GlebZ, Вы писали:

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


W>>Как быть? Есть какой-то надежный способ "поднять" окно?

GZ>Если ты сам в foreground, тогда чтобы более менее гарантированно необходимо вызвать AllowSetForegroundWindow на процесс. А дальше пусть он дальше кувыркается. Остальные способы более похожи на танцы с бубном.
Ничего не меняется, окно все равно не "всплывает". Да эти Foreground уже сами по себе танцы с бубном, ИМХО. Зачем мне делать какое-то окно foreground, мне нужно просто "альт-табнуть" указанный процесс.
Re[2]: Переместить окно поверх других.
От: Went  
Дата: 02.11.16 15:44
Оценка:
Здравствуйте, Carc, Вы писали:
C>Можно прицепить к вводу foreground-окна, используя AttachThreadInput и только потом всплывать через SetForegroundWindows.
Task Switcher так и делает?
Re[3]: Переместить окно поверх других.
От: Carc Россия https://vk.com/gosha_mazov
Дата: 02.11.16 15:55
Оценка: 2 (1)
Здравствуйте, Went, Вы писали:

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

C>>Можно прицепить к вводу foreground-окна, используя AttachThreadInput и только потом всплывать через SetForegroundWindows.
W>Task Switcher так и делает?
Вопросы по делу:
  1. А что такое Task Switcher?
  2. А что он делает?
  3. А как он это делает?
  4. А он говорит нам "что он сделает это с нами" (ц)?
  5. А почему я не телепат?
Что вообще нужно-то?
Просто отфореграундиться над произвольным окном и забрать фокус себе или что-то другое?
Aml Pages Home
Re: Переместить окно поверх других.
От: Mr.Delphist  
Дата: 02.11.16 16:08
Оценка: 2 (1) +4
Здравствуйте, Went, Вы писали:

W>Здравствуйте. Есть окно, чей хэндл мне известен. В общем случае оно может принадлежать другому процессу. Необходимо переместить окно поверх других (результат, аналогичный Alt + Tab-у на иконку данного приложения). Не могу подобрать WIN API функцию, которая бы дала нужный результат. Варианты, которые я попробовал:


Вариант 4: Не надо красть фокус ввода текущего приложения. НИКОГДА. Хочется привлечь внимание пользователя — "мигайте синим" в таскбаре, это абсолютно легально. Когда юзеру будет удобно — он переключится. Может, он сейчас пароль к фейсбуку набирает — а тут бац, и "I secretly love 50 cents" улетает в асечку.
Re[2]: Переместить окно поверх других.
От: CEMb  
Дата: 03.11.16 02:35
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>Вариант 4: Не надо красть фокус ввода текущего приложения. НИКОГДА.

Никогда не говори "никогда" А если человек пишет свой таскбар или иной таск манагер?

MD>Хочется привлечь внимание пользователя — "мигайте синим" в таскбаре, это абсолютно легально.


FlashWindowEx
Re: Переместить окно поверх других.
От: Evgeniy Skvortsov Россия  
Дата: 03.11.16 07:37
Оценка:
Здравствуйте, Went, Вы писали:

W>Как быть? Есть какой-то надежный способ "поднять" окно?


Ну ещё можно SetWindowPos попробовать.
Re[2]: Переместить окно поверх других.
От: Carc Россия https://vk.com/gosha_mazov
Дата: 03.11.16 08:32
Оценка:
Здравствуйте, Evgeniy Skvortsov, Вы писали:

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


W>>Как быть? Есть какой-то надежный способ "поднять" окно?


ES>Ну ещё можно SetWindowPos попробовать.

А чего оно даст-то для "альт-табнуть окно" по выражанию топик-стартера?
Aml Pages Home
Re[3]: Переместить окно поверх других.
От: VTT http://vtt.to
Дата: 03.11.16 08:57
Оценка: 6 (1)
Здравствуйте, Went, Вы писали:

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


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


W>>>Как быть? Есть какой-то надежный способ "поднять" окно?

GZ>>Если ты сам в foreground, тогда чтобы более менее гарантированно необходимо вызвать AllowSetForegroundWindow на процесс. А дальше пусть он дальше кувыркается. Остальные способы более похожи на танцы с бубном.
W>Ничего не меняется, окно все равно не "всплывает". Да эти Foreground уже сами по себе танцы с бубном, ИМХО. Зачем мне делать какое-то окно foreground, мне нужно просто "альт-табнуть" указанный процесс.

Дело в том, что возможность программно перевести окно на передний план (foreground) ограничена намеренно.
Подразумевается, что пользователь выбирает это окно сам, а приложения должны всегда следовать его выбору.
Если окно вашего приложения находится на переднем плане, то оно может вывести на передний план окно любого другого приложения или передать другому приложению возможность выходить на передний план (вызвав AllowSetForegroundWindow).
Если окно вашего приложения не находится на переднем плане, то перейти на передний план или вывести на передний план окно другого приложения просто так оно не может.

Если у вас два экземпляра приложения со своими окнами, и то из них, окно которого в данный момент не находится на переднем плане, хочет перейти на передний план, то следует попросить второй экземпляр приложения отдать первому экземпляру возможность перейти на передний план.
Если оба экземпляра приложения не находятся на переднем плане, то перейти на передний план (легальными методами) не удастся.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[4]: Переместить окно поверх других.
От: Carc Россия https://vk.com/gosha_mazov
Дата: 03.11.16 09:19
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>Если оба экземпляра приложения не находятся на переднем плане, то перейти на передний план (легальными методами) не удастся.

Почему не удастся-то!?! AttachThreadInput к окну, которое сейчас на переднем плане, т.е. то, которое GetForegroundWindow, и если AttachThreadInput завершилась успешно, то тогда поехали. И должно сработать. По моему ВинРар так и делает, когда после фоновой архивации подымается из трея. Он там любопытно подымается, ему пофиг какое окно фореграунд, встает из трея и забирает фокус себе как делать нечего.

Другой разговор, что прям щаззз (ц) вся окна подряд, а вернее потоки, которым принадлежат окна, так вам и разрешат цепляться к их очереди ввода (AttachThreadInput).
Aml Pages Home
Отредактировано 03.11.2016 9:20 Carc . Предыдущая версия .
Re[5]: Переместить окно поверх других.
От: VTT http://vtt.to
Дата: 03.11.16 09:31
Оценка: -1
Здравствуйте, Carc, Вы писали:

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


VTT>>Если оба экземпляра приложения не находятся на переднем плане, то перейти на передний план (легальными методами) не удастся.


C>Почему не удастся-то!?! AttachThreadInput к окну, которое сейчас на переднем плане, т.е. то, которое GetForegroundWindow, и если AttachThreadInput завершилась успешно, то тогда поехали. И должно сработать.

C>Другой разговор, что прям щаззз (ц) вся окна подряд, а вернее потоки, которым принадлежат окна, так вам и разрешат цепляться к их очереди ввода (AttachThreadInput).

Легальный метод — это AllowSetForegroundWindow / SetForegroundWindow.
Все остальные — это workaround / hack.
Но тс они явно не к чему.

C>По моему ВинРар так и делает, когда после фоновой архивации подымается из трея. Он там любопытно подымается, ему пофиг какое окно фореграунд, встает из трея и забирает фокус себе как делать нечего.

Ничего такого рар не делает, после архивации окно висит на заднем плане.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[6]: Переместить окно поверх других.
От: Carc Россия https://vk.com/gosha_mazov
Дата: 03.11.16 09:50
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>Легальный метод — это AllowSetForegroundWindow / SetForegroundWindow.

VTT>Все остальные — это workaround / hack.
Почему? AttachThreadInput чем хак-то!?!
Не спорю, что там много чего для нее понадобится. Ну та же OpenThread к чужому потоку, а она ну прям таки сразу всё и открыла. Запросто не отдаст хендл чужого потока. И соответственно схема просто не сработает. Но это вопрос чуток другой плоскости.

VTT>Но тс они явно не к чему.


C>>По моему ВинРар так и делает, когда после фоновой архивации подымается из трея. Он там любопытно подымается, ему пофиг какое окно фореграунд, встает из трея и забирает фокус себе как делать нечего.

VTT>Ничего такого рар не делает, после архивации окно висит на заднем плане.
Ну только что перепроверил (Вин7 х32, максимал). Всплыл как миленький из трея, и фокус себе захавал тоже. Причем поднялся он именно над Foregtound окном, а вовсе не оттуда откуда он запускался (Total Commander причем пущенный без админских прав)... Настораживает.
Aml Pages Home
Re[6]: Переместить окно поверх других.
От: Carc Россия https://vk.com/gosha_mazov
Дата: 03.11.16 10:08
Оценка:
Здравствуйте, VTT, Вы писали:


VTT>Легальный метод — это AllowSetForegroundWindow / SetForegroundWindow.

VTT>Все остальные — это workaround / hack.
Ну вот вам функция, которая дергается по таймеру. Всплывает мое окно как миленькое, и фокус себе забирает у кого хочешь. Но как говорил, все будет зависеть от прав: если успешно отработает AttachThreadInput к чужому потоку.
    const HWND hwnd=::GetForegroundWindow();//кто у нас фореграунд-окно сейчас

    DWORD pid =0;
    
    //получаем ThreadID и ProcessID окна на переднем плане
    const DWORD tid=::GetWindowThreadProcessId(hwnd,&pid);

    //если окно переднего плана и так наше, ту хулио нам хулио (ц) - мы и без атача всё можем
    if (GetCurrentProcessId() == pid)
        return;
    
    //подключаемся к очереди ввода, но тут могет быть неудача - из-за безопасности Windows    
    if (AttachThreadInput(GetCurrentThreadId(), tid,TRUE)) {
        //ага, мль подключилися значитъ - ну поехали тогда
        ::SetForegroundWindow(m_hWnd);//m_hWnd - это HWND нашего окна, откуда по по таймеру для теста дергается эта функция
        ::SetActiveWindow(m_hWnd);
        ::SetFocus(m_hWnd);
        //отключаемся от очереди ввода к чужому окошецу
        AttachThreadInput(GetCurrentThreadId(), tid,FALSE);
    }
Aml Pages Home
Отредактировано 03.11.2016 10:11 Carc . Предыдущая версия . Еще …
Отредактировано 03.11.2016 10:10 Carc . Предыдущая версия .
Отредактировано 03.11.2016 10:10 Carc . Предыдущая версия .
Отредактировано 03.11.2016 10:09 Carc . Предыдущая версия .
Re[7]: Переместить окно поверх других.
От: VTT http://vtt.to
Дата: 03.11.16 10:13
Оценка: +2 -1
Здравствуйте, Carc, Вы писали:

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


VTT>>Легальный метод — это AllowSetForegroundWindow / SetForegroundWindow.

VTT>>Все остальные — это workaround / hack.
C>Почему? AttachThreadInput чем хак-то!?!
А тем, что пытается ввести систему в заблуждение, что пользователь осуществил ввод в этот процесс, и получить не причитающуюся ему привилегию на перенос окна на передний план.

C>>>По моему ВинРар так и делает, когда после фоновой архивации подымается из трея. Он там любопытно подымается, ему пофиг какое окно фореграунд, встает из трея и забирает фокус себе как делать нечего.

VTT>>Ничего такого рар не делает, после архивации окно висит на заднем плане.
C>Ну только что перепроверил (Вин7 х32, максимал). Всплыл как миленький из трея, и фокус себе захавал тоже. Причем поднялся он именно над Foregtound окном, а вовсе не оттуда откуда он запускался (Total Commander причем пущенный без админских прав)... Настораживает.

Ну только что перепроверил (Вин10 х64, про). Всплыл как миленький на заднем плане, и фокус себе не захватывал.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[8]: Переместить окно поверх других.
От: Carc Россия https://vk.com/gosha_mazov
Дата: 03.11.16 10:34
Оценка:
Здравствуйте, VTT, Вы писали:

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


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


VTT>>>Легальный метод — это AllowSetForegroundWindow / SetForegroundWindow.

VTT>>>Все остальные — это workaround / hack.
C>>Почему? AttachThreadInput чем хак-то!?!
VTT>А тем, что пытается ввести систему в заблуждение, что пользователь осуществил ввод в этот процесс, и получить не причитающуюся ему привилегию на перенос окна на передний план.
Бред. Если ему не положены привилегии, то AttachThreadInput завершится неудачей, и ничего не выйдет. А система не должна зависеть от того, пытается ли ее кто-нить ввести в заблуждение, или еще чего куда ввести. Нет привилегий — и не сработает. Никто и не спорил. Но сам способ с AttachThreadInput вовсе не хак, а официальный API.

C>>>>По моему ВинРар так и делает, когда после фоновой архивации подымается из трея. Он там любопытно подымается, ему пофиг какое окно фореграунд, встает из трея и забирает фокус себе как делать нечего.

VTT>>>Ничего такого рар не делает, после архивации окно висит на заднем плане.
C>>Ну только что перепроверил (Вин7 х32, максимал). Всплыл как миленький из трея, и фокус себе захавал тоже. Причем поднялся он именно над Foregtound окном, а вовсе не оттуда откуда он запускался (Total Commander причем пущенный без админских прав)... Настораживает.

VTT>Ну только что перепроверил (Вин10 х64, про). Всплыл как миленький на заднем плане, и фокус себе не захватывал.

Над кем не всплыл? Надо всеми подряд и не должен всплывать.
Я уже писал, что проверял на своем коде. Мое приложение работало из под ограниченной учетки, соседние приложения по разному. Мой код всплывания дергался каждые полторы секунды. Дык вот ессесна над приложениями с более высокими правами мое добро и не всплывало, ибо
AtttachThreadInput заканчивался неудачей. Что ожидаемо, и я изначально это описал.
Aml Pages Home
Отредактировано 03.11.2016 10:35 Carc . Предыдущая версия .
Re[9]: Переместить окно поверх других.
От: VTT http://vtt.to
Дата: 03.11.16 11:08
Оценка: +1
Здравствуйте, Carc, Вы писали:

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


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


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


VTT>>>>Легальный метод — это AllowSetForegroundWindow / SetForegroundWindow.

VTT>>>>Все остальные — это workaround / hack.
C>>>Почему? AttachThreadInput чем хак-то!?!
VTT>>А тем, что пытается ввести систему в заблуждение, что пользователь осуществил ввод в этот процесс, и получить не причитающуюся ему привилегию на перенос окна на передний план.
C>Бред. Если ему не положены привилегии, то AttachThreadInput завершится неудачей, и ничего не выйдет. А система не должна зависеть от того, пытается ли ее кто-нить ввести в заблуждение, или еще чего куда ввести. Нет привилегий — и не сработает. Никто и не спорил.

C>>>>>По моему ВинРар так и делает, когда после фоновой архивации подымается из трея. Он там любопытно подымается, ему пофиг какое окно фореграунд, встает из трея и забирает фокус себе как делать нечего.

VTT>>>>Ничего такого рар не делает, после архивации окно висит на заднем плане.
C>>>Ну только что перепроверил (Вин7 х32, максимал). Всплыл как миленький из трея, и фокус себе захавал тоже. Причем поднялся он именно над Foregtound окном, а вовсе не оттуда откуда он запускался (Total Commander причем пущенный без админских прав)... Настораживает.

C>Я уже писал, что проверял на своем коде. Мое приложение работало из под ограниченной учетки, соседние приложения по разному. Мой код всплывания дергался каждые полторы секунды. Дык вот ессесна над приложениями с более высокими правами мое добро и не всплывало, ибо

C>AtttachThreadInput заканчивался неудачей. Что ожидаемо, и я изначально это описал.

Воу воу, полешче, хватит лепить мне минусы. У вас же сплошной винигрет.
Привилегия в данном случае — это возможность отправить окно на передний план или передать такую возможность другому процессу.
А не "запущенность с правами администратора" или какая другая системная привилегия.
О взаимодействия с процессами, запущенными из-под привилегированных пользователей и к которым могут применяться методы изоляции, тут речи вообще не шло.

C>Но сам способ с AttachThreadInput вовсе не хак, а официальный API.

Это официальный API, но его использование для обхода ограничений SetForegroundWindow — это если и не хак, то наглый workaround.
Если окно не на переднем плане и SetForegroundWindow не работает, то оно так и должно сидеть дальше и ждать, пока пользователь сам в него переключится.
Как максимум, оно может вызвать FlashWindow чтобы привлечь внимание пользователя.

VTT>>Ну только что перепроверил (Вин10 х64, про). Всплыл как миленький на заднем плане, и фокус себе не захватывал.

C>Над кем не всплыл? Надо всеми подряд и не должен всплывать.
Да ни над кем не всплыл.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[3]: Переместить окно поверх других.
От: Evgeniy Skvortsov Россия  
Дата: 03.11.16 11:24
Оценка:
Здравствуйте, Carc, Вы писали:

C>А чего оно даст-то для "альт-табнуть окно" по выражанию топик-стартера?


Ну вроде же она меняет z-order у окон.
Re[10]: Переместить окно поверх других.
От: Carc Россия https://vk.com/gosha_mazov
Дата: 03.11.16 11:42
Оценка:
C>>Но сам способ с AttachThreadInput вовсе не хак, а официальный API.
VTT>Это официальный API, но его использование для обхода ограничений SetForegroundWindow — это если и не хак, то наглый workaround.
VTT>Если окно не на переднем плане и SetForegroundWindow не работает, то оно так и должно сидеть дальше и ждать, пока пользователь сам в него переключится.
VTT>Как максимум, оно может вызвать FlashWindow чтобы привлечь внимание пользователя.
Мы обсуждали способ решения, а вовсе не юзабилити. Что оно там должно или не должно — решать топик-стартеру, тем более что он не очень то внятно пояснил, чего ему по сути надо. Особенно настараживает фраза "мне всего лишь нужно альтабнуть окно".

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

Я имею ввиду именно пользовательские действия, что все таки пользователь именно что сам нажмет Alt+Tab, дальше уже софтино само все сделает. Но обратите внимание на посылку: пользователь жмёт Альт+Таб сам — т.е. сначала ручками делает нужному окну foreground, а только потом...

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

Но разговор то изначальный о другом был... О способах, а не о практиках, и их достоинствах и недостатках (ВинРар кстати иногда мешает такой своей премудростью, хотя и впечатляет).
Aml Pages Home
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.