Избегайте активации приложения и сосредотачивайтесь при нажатии кнопок на нем - Windows API или Qt

Ситуация: QDialog без границ успешно работает поверх других приложений.

Проблема заключается в том, что при нажатии на это постоянно открывающееся окно приложения происходит следующее:

  • Активируется приложение, которое всегда отображается сверху.
  • Окно приложения, по которому всегда щелкают, перехватывает фокус предыдущего активного / сфокусированного приложения.

Есть ли вероятность того, что при нажатии на это всегда вверху неактивное и несфокусированное окно приложения,

  • текущее приложение не теряет активацию и фокус
  • в то время как пользователь по-прежнему может взаимодействовать с приложением, которое всегда отображается наверху (нажатие кнопок или раскрывающихся меню, перетаскивание окна)?

Я работаю с Qt, но нет проблем с использованием собственного Windows API.

Я пробовал следующий Qt windowFlag:

  • Qt::WindowDoesNotAcceptFocus но не работает: приложение Always-on-Top активировано, сфокусировано.
  • Qt::WindowTransparentForInput, приложение «Всегда поверх экрана» действительно прозрачно для щелчков: не активировано и не сфокусировано, но кнопки, к сожалению, не срабатывают при нажатии.

person Derek    schedule 06.09.2013    source источник


Ответы (2)


Можно сделать окно неактивным и нефокусируемым при щелчке по нему с помощью флагов Windows (#include <qt_windows.h>). После создания и отображения окна необходимо использовать следующее:

HWND winHandle = (HWND)winId();
ShowWindow(winHandle, SW_HIDE);
SetWindowLong(winHandle, GWL_EXSTYLE, GetWindowLong(winHandle, GWL_EXSTYLE)
    | WS_EX_NOACTIVATE | WS_EX_APPWINDOW);
ShowWindow(winHandle, SW_SHOW);
person Derek    schedule 12.09.2013
comment
Хм, как вы вообще это делаете в Qt? Заменить winEvents? - person swdev; 04.07.2014
comment
Вы можете переопределить showEvent(). Для его реализации сначала вызовите родительский метод, а затем приведенный выше код. - person Derek; 05.07.2014
comment
Неудачно :) Мне уже удалось перенести код на PyQt с использованием библиотек PyWin, переопределив showEvent(), но когда я нажимаю элемент управления в этом предполагаемом неактивном окне, мое главное окно становится неактивным. Любая идея? - person swdev; 06.07.2014
comment
А как насчет переопределения showEvent() и в другом окне? - person Derek; 07.07.2014
comment
Мой случай - это плавающий QFrame, содержащий кнопки, которые нужно нажимать. Не удалось использовать вышеуказанный WS_EX_NOACTIVATE. Прямо сейчас я создаю подкласс pushbutton и захватываю MouseButtonPress, MouseButtonRelease и MouseButtonDblClick в eventFilter. Там я активирую главное окно. Это почти идеально. Иногда по-прежнему быстро мигала строка заголовка. Но, да, это лучшее, что я могу сделать прямо сейчас :) - person swdev; 08.07.2014
comment
Активно ли окно при нажатии на его фон (а не на одну из его кнопок). Я помню, что мне пришлось переопределить showEvent () в меню / раскрывающемся списке окна. - person Derek; 08.07.2014
comment
Мой фон прозрачный. Таким образом, в этом случае пользователи должны нажать кнопку. Я также переопределил showEvent() подкласса кнопок и попытался установить там WS_EX_NOACTIVATE. Но все же фокус сместился с главного окна - person swdev; 08.07.2014
comment
Попробуйте новый простой проект Qt с одним окном по умолчанию (без специальных эффектов, без прозрачного фона, без кнопок ...). Посмотрите, не активирует ли приложение щелчок по окну, а затем проб / ошибок различные варианты (добавление кнопок, прозрачность, несколько окон ...). - person Derek; 09.07.2014

Я не знаю о QDialog, я использую только QWidget для аналогичной цели (отображение уведомления в стиле Windows 8).

Попробуйте установить:

dialog->setFocusPolicy(Qt::NoFocus);
dialog->setAttribute(Qt::WA_ShowWithoutActivating); 

возможно, вам придется сосредоточить политику на всех детях.

person headsvk    schedule 07.09.2013
comment
Спасибо, Headsvk, но он отменяется флагом всегда сверху: dialog->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); Похоже, что этот флаг конфликтует с атрибутом Qt::WA_ShowWithoutActivating. - person Derek; 09.09.2013
comment
На самом деле он вообще не работает в Windows (даже без WindowStaysOnTopHint), а на Mac есть конфликт. Я тестировал MainWindow, затем QDialog и, наконец, QWidget. - person Derek; 09.09.2013
comment
Я тоже использую Qt::WindowStaysOnTopHint. Поэтому я попытался добавить кнопку в свое всплывающее окно, и когда я нажимаю на нее, она не крадет фокус моего активного окна. Как конфликтуют флаги? - person headsvk; 09.09.2013
comment
Конфликт был на Mac (извините за недоразумение). Но вернемся к Windows. Приложение по-прежнему активируется и получает фокус. Я создал образец проекта Qt GUI, а затем добавил следующий код в конструктор MainWindow: pastebin .com / tKB2NSHz - person Derek; 11.09.2013
comment
хорошо, это не работает для меня, мое всплывающее окно не крадет фокус на шоу, поэтому я подумал, что он также не щелкает (я не нажимаю на него, я закрываю его при вводе мыши), извините - person headsvk; 11.09.2013
comment
однако, если окно, которое должно оставаться активным, принадлежит вам, вы можете использовать простой обходной путь, активировав его, когда пользователь нажимает на диалоговое окно. - person headsvk; 11.09.2013
comment
К сожалению, это не так. Как правило, мое приложение Qt (которое следует оставить неактивированным и несфокусированным) находится поверх PowerPoint. - person Derek; 11.09.2013