Brief description: After the new window is summoned by the global hotkey, Do not click the tray icon and associated windows of this program (but can be moved, with cursor tracking turned on), and just click the keyboard keys without any response. but After clicking, it can respond key is pressed. Fix this weird problem.
[TOC]
This article was originally published on ” Xie Zang’s Small Station “, and is reproduced here simultaneously.
win10 21H2
Qt 5.12.11
background
When writing a screenshot, when the source code is in the IDE, after compiling and running, a托盘图标
appear in the lower right, indicating that the program is running. At this time, the截图窗口
can be successfully summoned by the shortcut key F6
(no title bar + maximized). + stick to the top).
The operation is as follows: At this time, the mouse deliberately does not click on the截图窗口
and托盘图标
, but only moves, and you can see the change of the absolute coordinates of the cursor in the real-time display. At this point, press the shortcut key Esc
, the截图窗口
will not disappear. Strange? ? ? But if you right-click on the tray menu, call the截图窗口
, and press Esc
to close the response. Subsequent shortcuts to summon the截图窗口
and Esc
are always normal.
analyze
At first, it was thought that the program lacked focus. Trying the two methods of setting focus in [QT] New pop-up window defaults to no focus , both are invalid.
Simply write a TestHotKey to verify this global hotkey function, why?
The pallet related code is as follows
// -------------------- tray.h -------------------- class Tray : public QObject { Q_OBJECT public : explicit Tray ( QObject * parent = nullptr ) ; public slots : void onScreenShot ( ) ; private : QAction * m_screenShot ; QAction * m_quit ; QMenu * m_menuTary ; QSystemTrayIcon * m_sysTary ; QHotkey * m_hkScrnShot ; // 热键} ; // -------------------- tray.cpp -------------------- Tray :: Tray ( QObject * parent ) : QObject ( parent ) , m_screenShot ( nullptr ) , m_quit ( nullptr ) , m_menuTary ( nullptr ) , m_sysTary ( nullptr ) , m_hkScrnShot ( new QHotkey ( QKeySequence ( "f2" ) , true , qApp ) ) { m_screenShot = new QAction ( tr ( "ScreenShot" ) , this ) ; m_quit = new QAction ( tr ( "Quit" ) , this ) ; m_menuTary = new QMenu ( ) ; m_menuTary -> addAction ( m_screenShot ) ; m_menuTary -> addSeparator ( ) ; m_menuTary -> addAction ( m_quit ) ; m_sysTary = new QSystemTrayIcon ( this ) ; m_sysTary -> setIcon ( QIcon ( ":/resources/PicShot_32.svg" ) ) ; m_sysTary -> setToolTip ( tr ( "PicShot Test" ) ) ; m_sysTary -> setContextMenu ( m_menuTary ) ; m_sysTary -> setVisible ( true ) ; // 快捷键响应connect ( m_hkScrnShot , & QHotkey :: activated , this , & Tray :: onScreenShot ) ; // 右键菜单触发connect ( m_screenShot , & QAction :: triggered , this , & Tray :: onScreenShot ) ; connect ( m_quit , & QAction :: triggered , [ ] ( ) { qApp -> quit ( ) ; } ) ; } void Tray :: onScreenShot ( ) { auto & ins = Widget :: instance ( ) ; ins . show ( ) ; }
The screenshot window code is as follows:
// -------------------- tray.cpp -------------------- Widget :: Widget ( QWidget * parent ) : QWidget ( parent ) { setFocusPolicy ( Qt :: StrongFocus ) ; QDesktopWidget * desktop = QApplication :: desktop ( ) ; // 获取桌面的窗体对象const QRect geom = desktop -> geometry ( ) ; // 多屏的矩形取并集setWindowFlags ( Qt :: FramelessWindowHint /*| Qt::WindowStaysOnTopHint */ | windowFlags ( ) ) ; // 去掉标题栏+ 置顶// setAttribute(Qt::WA_ShowWithoutActivating,true); // setFocusPolicy(Qt::StrongFocus); // setFixedSize(QSize(geom.size().width() / 4, geom.size().height())); setFixedSize ( QSize ( 512 , geom . size ( ) . height ( ) ) ) ; setMouseTracking ( true ) ; } void Widget :: keyPressEvent ( QKeyEvent * event ) { if ( event -> key ( ) == Qt :: Key_Escape ) { qDebug ( ) << "Key_Escape" ; hide ( ) ; } else if ( event -> key ( ) == Qt :: Key_A ) { qDebug ( ) << "Key_A" ; } } void Widget :: paintEvent ( QPaintEvent * event ) { QPainter pa ( this ) ; pa . drawText ( 100 , 200 , QString ( "m_pos(%1, %2)" ) . arg ( m_pos . x ( ) ) . arg ( m_pos . y ( ) ) ) ; }
The breakthrough point is in Widget::keyPressEvent()
, if you want to know whether the corresponding state will respond to keyboard keys, you can find the reason by confirming this.
root cause resolution
This idea feels a bit O’Henry-style:
Know this article -> tab switch window -> think of the activation window -> google key: focus becomes window activation, -> remove the top and try (remove interference factors) -> ok
The screenshot window summoned by using the global hotkey does not belong to the active window at this time. The solution is to set this window as the active window after show() again.
void Tray :: onScreenShot ( ) { auto & ins = Widget :: instance ( ) ; ins . show ( ) ; // 解决方案: show() 之后,设置为激活窗口即可if ( ! ins . isActiveWindow ( ) ) ins . activateWindow ( ) ; }
Serial address
QtExamples “TestHotKey”
welcome star
and fork
This series of C++ / QT / DTK
learning, with a directory of learning from shallow to deep.
refer to
- Qt Drawing: Inspired by Keyboard Focus in Widgets
- Although some experience of focus setting in Qt interface is not different, the reference article has the value of focus understanding
- The QT activation window has not been tried. If this article is not resolved, you can try this method
This article is reproduced from: https://ifmet.cn/posts/44eabb4d/
This site is for inclusion only, and the copyright belongs to the original author.