1. QSystemTrayIcon hover事件

参考:https://stackoverflow.com/questions/21795919/how-to-catch-the-mousehover-event-for-qsystemtrayicon

There is no cross-platform solution for the hover event of QSystemTrayIcon, yet (Qt5.7). You are lucky, when you are on X11: Only on X11, when a tooltip is requested, the QSystemTrayIcon receives a QHelpEvent of type QEvent::ToolTip. Additionally, the QSystemTrayIcon receives wheel events of type QEvent::Wheel. **These are not supported on any other platform.** – Jens A. Koch Dec 4 '16 at 22:34

We can only get mouse move, up, down, and double-click messages from the system tray.

QT没有QSystemTrayIcon托盘hover事件,只有X11系统上可以捕捉。目前只能捕捉单击、双击、右击等动作。

参考:https://www.cnblogs.com/xiang--liu/p/12034608.html

没有捕捉到托盘事件。

2. 使用NOTIFYICONDATA

https://www.cnblogs.com/qnkk123/p/6840944.html

3.  开启一个线程/定时器去监听

驻留多一个线程,来判断鼠标是否在托盘图标区域上

托盘区域:

QSystemTrayIcon *trayicon = new QSystemTrayIcon();

x轴:    trayicon->geometry().x();
y轴:    trayicon->geometry().y();
宽度:    trayicon->geometry().width();
高度:    trayicon->geometry().height();

QCursor::pos();//获取当前光标的位置

设定定时器,每过2秒去查看是否停留在托盘区域

QTimer *trayTimer=new QTimer();

trayTimer->start(2000); //每500ms都刷新一次

trayTimer->setSingleShot(false); //如果为真,表示只重复一次,为假表示无限次循环

connect(trayTimer,SIGNAL(timeout()),this,SLOT(checkMousePos()));

void MainWindow::checkMousePos()

{
    qDebug() << "iconIsActived:"<<trayicon->geometry().x();
    qDebug() << "iconIsActived:"<<trayicon->geometry().y();
    qDebug() << "iconIsActived:"<<trayicon->geometry().width();
    qDebug() << "iconIsActived:"<<trayicon->geometry().height();
    qDebug() << "鼠标位置x:"<<QCursor::pos().x();
    qDebug() << "鼠标位置y:"<<QCursor::pos().y();

    int xMin = trayicon->geometry().x();
    int xMax = trayicon->geometry().x()+trayicon->geometry().width();

    int yMin = trayicon->geometry().y();
    int yMax = trayicon->geometry().y()+trayicon->geometry().height();

    int x = QCursor::pos().x();
    int y = QCursor::pos().y();

    qDebug() << "xMin<=x&&x<=xMax:"<<(xMin<=x&&x<=xMax);
    qDebug() << "yMin<=y&&y<=yMax:"<<(yMin<=y&&y<=yMax);

    if(xMin<=x&&x<=xMax
            &&yMin<=y&&y<=yMax){
        qDebug() << "托盘中";
    }else{
        qDebug() << "不在托盘中";
    }
}

完整代码示例

CCailianMainWindow.pro

#-------------------------------------------------
#
# Project created by QtCreator 2019-12-13T13:16:48
#
#------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = CCailianMainWindow
TEMPLATE = app # The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 CONFIG += c++11 SOURCES += \
main.cpp \
mainwindow.cpp HEADERS += \
mainwindow.h FORMS += \
mainwindow.ui # Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QSystemTrayIcon>
#include <QMainWindow>
#include <QAbstractNativeEventFilter> namespace Ui {
class MainWindow;
} class MainWindow : public QMainWindow,public QAbstractNativeEventFilter
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
bool nativeEventFilter(const QByteArray & eventType, void * message, long * result); private:
void closeEvent(QCloseEvent *); //在关闭窗口时候要重写该函数,为了最小化到托盘,而不是退出程序
void initTray(); //程序设计的托盘初始化 private slots:
void onSystemTrayIconClicked(QSystemTrayIcon::ActivationReason reason); /*托盘*/
void MenuExit(); //右键菜单 退出
void ShowNormal(); //正常显示
void minNormal( );
void iconIsActived(QSystemTrayIcon::ActivationReason); //托盘图表活动,无论是鼠标悬浮,或者双击,或者单击
void ShowClickMsg(); //点击了消息框后的响应函数
void flicker_msg_com();
void updateIcon(); //定时器刚
void ShowMessageBox(); //像是托盘图表的messagebox() void checkMousePos(); private:
Ui::MainWindow *ui;
}; #endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"
#include <QApplication> int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show(); a.installNativeEventFilter(&w); return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QMessageBox>
#include <QSystemTrayIcon>
#include <QTimer> #include <windows.h>
#pragma comment(lib, "user32.lib") QTimer *flipTimer=new QTimer();
QTimer *trayTimer=new QTimer();
int TimerCount;
QSystemTrayIcon *trayicon = new QSystemTrayIcon(); MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initTray();
} MainWindow::~MainWindow()
{
delete ui;
} //只能捕捉窗口范围内的鼠标事件,并不能捕捉托盘内的鼠标事件
bool MainWindow::nativeEventFilter(const QByteArray & eventType, void * message, long * result)
{
if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG")
{
MSG * pMsg = reinterpret_cast<MSG *>(message); if (pMsg->message == WM_MOUSEMOVE)
{ //获取到系统鼠标移动,可以做像qq一样的忙碌检测
qDebug() << "nativeEventFilter:"<<pMsg->pt.x;
}
} return false;
} /* 5. 托盘图标显示、隐藏 */
void MainWindow::onSystemTrayIconClicked(QSystemTrayIcon::ActivationReason reason)
{
switch(reason)
{
//单击
case QSystemTrayIcon::Trigger:
//双击
case QSystemTrayIcon::DoubleClick:
if(this->isHidden())
{
//恢复窗口显示
this->show();
//一下两句缺一均不能有效将窗口置顶
this->setWindowState(Qt::WindowActive);
this->activateWindow();
}
else
{
this->hide();
}
break;
default:
break;
}
} void MainWindow::initTray() {
connect(trayicon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(onSystemTrayIconClicked(QSystemTrayIcon::ActivationReason))); //1. 设置定时器去闪烁图标
TimerCount=0; //初始化为零 //2. 添加托盘右键菜单
QMenu *contexmenu=new QMenu(this); //注意右键菜单的父对象,在窗口销毁后要把菜单也销毁掉 QAction *openNomal=new QAction(this);
QAction *minNomal=new QAction(this);
QAction *action_quit=new QAction(this);
QAction *flicker_test=new QAction(this); openNomal->setText(QString("显示"));
openNomal->setIcon(QIcon(":/resources/images/tray/tray.png")); minNomal->setText(QString("最小化到托盘"));
minNomal->setIcon(QIcon(":/resources/images/button/min.png"));
// QPixmap minPix = style()->standardPixmap(QStyle::SP_TitleBarMinButton);
// minNomal->setIcon(minPix); action_quit->setText(QString("退出"));
action_quit->setIcon(QIcon(":/resources/images/button/quit.png")); flicker_test->setText(QString("闪烁测试"));
flicker_test->setIcon(QIcon(":/resources/images/tray/flicker.png")); contexmenu->addAction(openNomal);
contexmenu->addSeparator();
contexmenu->addAction(minNomal);
contexmenu->addSeparator();
contexmenu->addAction(action_quit);
// contexmenu->addSeparator();
// contexmenu->addAction(flicker_test); connect(openNomal,SIGNAL(triggered()),this,SLOT(ShowNormal()));
connect(minNomal, SIGNAL(triggered()), this, SLOT( minNormal()) );
connect(action_quit,SIGNAL(triggered()),this,SLOT(MenuExit()));
connect(flicker_test,SIGNAL(triggered()),this,SLOT(flicker_msg_com())); trayicon->setContextMenu(contexmenu); //3. 添加托盘图标
QIcon taskIcon;
taskIcon.addFile(":/resources/images/tray/tray.png");
//icon的大小调整??? QIcon trayIcon;
trayIcon.addFile(":/resources/images/tray/trayIcon.ico"); trayicon->setIcon(trayIcon); //9. 托盘图标提示
trayicon->setToolTip("桌面端");
trayicon->show(); //10. 设置任务栏图标
this->setWindowIcon(taskIcon);
this->setWindowTitle(tr("桌面端")); //11. 托盘闪烁 //10. 托盘菜单(右击功能) connect(trayicon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(iconIsActived(QSystemTrayIcon::ActivationReason)));
connect(trayicon,SIGNAL(messageClicked()),this,SLOT(ShowClickMsg())); trayTimer->start(2000); //每500ms都刷新一次
trayTimer->setSingleShot(false); //如果为真,表示只重复一次,为假表示无限次循环
connect(trayTimer,SIGNAL(timeout()),this,SLOT(checkMousePos())); } /* initTray()槽函数区 */
/* 1. 右键菜单正常显示*/
void MainWindow::ShowNormal()
{
flipTimer->stop();
trayicon->setIcon(QIcon(":/resources/images/tray/trayIcon.png")); //正常显示时候恢复原有图标,防止定时器在无显示图表时候被终止
// this->show(); if( windowState() == Qt::WindowMinimized ){
setWindowState( Qt::WindowNoState );
}
} /* 2. 右键菜单最小化*/
void MainWindow::minNormal()
{
if( windowState() != Qt::WindowMinimized ){
setWindowState( Qt::WindowMinimized );
}
} /* 3. 响应右键菜单 关闭程序*/
void MainWindow::MenuExit()
{ exit(0);
} /* 4. 模拟告警消息到来时候,托盘图表闪动*/
void MainWindow::flicker_msg_com()
{
flipTimer->start(500); //每500ms都刷新一次
flipTimer->setSingleShot(false); //如果为真,表示只重复一次,为假表示无限次循环
connect(flipTimer,SIGNAL(timeout()),this,SLOT(updateIcon()));
}
//刷新托盘图标
void MainWindow::updateIcon()
{
TimerCount++;
if(TimerCount%2)
{
trayicon->setIcon(QIcon(":/new/prefix1/0")); //实际上没有这个图标,然后会显示没有图表
}
else
{
trayicon->setIcon(QIcon(":/resources/images/tray/trayIcon.png"));
}
} //托盘图标活动
void MainWindow::iconIsActived(QSystemTrayIcon::ActivationReason reason)
{
switch(reason)
{
case QSystemTrayIcon::DoubleClick:
ShowNormal();
break;
// case QSystemTrayIcon::Trigger:
// ShowMessageBox();
// break;
case QSystemTrayIcon::Unknown:
QMessageBox::about(this,"unkown","unkown activation");
break;
default:
break;
}
}
void MainWindow::ShowMessageBox()
{
QSystemTrayIcon::MessageIcon icon=QSystemTrayIcon::MessageIcon(1); //设置图表是标准的系统托盘 信息
trayicon->showMessage("you click","hello,tray",icon,10000);
}
//点击了消息框后的要响应的函数
void MainWindow::ShowClickMsg()
{
// QMessageBox::about(this,"click","you click the messagebox");
ShowNormal();
} //相应关闭窗口消息函数
void MainWindow::closeEvent(QCloseEvent *event)
{
if(trayicon->isVisible())
{
QMessageBox::StandardButton questionResult;//返回选择的 按钮
questionResult= QMessageBox::question(this,tr("桌面端"),tr("最小化到托盘")); if(questionResult == QMessageBox::Yes){
// this->hide();
setWindowState( Qt::WindowMinimized );
// event->ignore();//如果不想关闭窗口,必须显示调用ignore(),否则窗口默认会关闭
}
else{
//清除系统托盘图标
trayicon->setIcon(QIcon(":/new/prefix1/0"));
exit(0);
}
} } void MainWindow::checkMousePos()
{
qDebug() << "iconIsActived:"<<trayicon->geometry().x();
qDebug() << "iconIsActived:"<<trayicon->geometry().y();
qDebug() << "iconIsActived:"<<trayicon->geometry().width();
qDebug() << "iconIsActived:"<<trayicon->geometry().height();
qDebug() << "鼠标位置x:"<<QCursor::pos().x();
qDebug() << "鼠标位置y:"<<QCursor::pos().y(); int xMin = trayicon->geometry().x();
int xMax = trayicon->geometry().x()+trayicon->geometry().width(); int yMin = trayicon->geometry().y();
int yMax = trayicon->geometry().y()+trayicon->geometry().height(); int x = QCursor::pos().x();
int y = QCursor::pos().y(); qDebug() << "xMin<=x&&x<=xMax:"<<(xMin<=x&&x<=xMax);
qDebug() << "yMin<=y&&y<=yMax:"<<(yMin<=y&&y<=yMax); if(xMin<=x&&x<=xMax
&&yMin<=y&&y<=yMax){
qDebug() << "托盘中";
}else{
qDebug() << "不在托盘中";
}
}

QT 托盘 hover事件捕捉的更多相关文章

  1. Qt之键盘事件监听-实时响应大小写Capslock按键

    目录 一.开篇 二.效果展示 三.实现思路 1.重写QLlinEdit 2.全局应用程序事件 3.windows钩子 四.相关文章 原文链接:Qt之键盘事件监听-实时响应大小写Capslock按键 一 ...

  2. jQuery中多个元素的Hover事件

    1.需求简介 jQuery的hover事件只是针对单个HTML元素,例如: $('#login').hover(fun2, fun2); 当鼠标进入#login元素时调用fun1函数,离开时则调用fu ...

  3. 用:hover伪类代替js的hover事件

    制作二级菜单要实现鼠标移动上去显示子菜单,鼠标移出子菜单隐藏,或者其他类似需求的地方,首先我会想到用jquery的hover事件来实现,如: $(".nav").hover(fun ...

  4. 获得触发hover事件的元素id

    例: <div class="menu"> <ul> <li> <a id="menu1"></a> ...

  5. jquery中取消和绑定hover事件的正确方式

    在网页设计中,我们经常使用jquery去响应鼠标的hover事件,和mouseover和mouseout事件有相同的效果,但是这其中其中如何使用bind去绑定hover方法呢?如何用unbind取消绑 ...

  6. hover事件优化(延时操作)

    JQ的hover事件拓展 编写原因:当鼠标滑过某个带有hover事件的元素,但是仅仅是路过,并不是希望查看此部分内容的时候,效果不理想 $.fn.extend({ delayed : function ...

  7. 鼠标经过(hover)事件的延时处理

    关于鼠标hover事件及延时 鼠标经过事件为web页面上最常见的事件之一.简单的hover可以用CSS :hover伪类实现,复杂点的用js. 一般情况下,我们是不对鼠标hover事件进行延时处理.但 ...

  8. Qt中的事件

    1. 引自---http://blog.sina.com.cn/s/blog_6e80f1390100pro4.html 信号和事件的区别就在与,事件比信号更加底层,而且如果一个信号对应多个槽的话,信 ...

  9. jQuery hover事件鼠标滑过图片半透明标题文字滑动显示隐藏

    1.效果及功能说明 hover事件制作产品图片鼠标滑过图片半透明,标题文字从左到右滑动动画移动显示隐藏 2.实现原理 首先把效果都隐藏,然后定义一个伪类来触发所有的效果,接下来当触发伪类后会有一个遍历 ...

随机推荐

  1. 如何引用vue

    Vue.js 安装 https://www.runoob.com/vue2/vue-install.html 1.独立版本 我们可以在 Vue.js 的官网上直接下载 vue.min.js 并用 &l ...

  2. 【转】java导出多个excel表格,并压缩成zip输出

    转自:http://blog.csdn.net/qq_14861089/article/details/53169414    感谢作者分享 /** * 导出支付宝批量支付文件excel * * @p ...

  3. 麦香牛肉(dp 、数论)

    麦香牛肉 时间限制: 1 Sec  内存限制: 128 MB 题目描述 农夫约翰的奶牛几乎要武装暴动,因为他们听说麦当劳要推出新产品麦香牛肉.奶牛们要尽力阻止这种产品的上市.他们研究了一种“劣等包装” ...

  4. azure sql database CPU troubleshooting

    描述 最新我们一个稳定运行快一年的项目突然出现CPU方面的性能问题,该项目使用的azure sql database  P2 500DTU,运维同事监控到CPU使用非常高,客户反馈系统运行也比较卡.看 ...

  5. ANSI C遍历二维数组指针地址

    #include <stdio.h> int main() { ][] = {,,,}; //等价于{{1,2},{3,4}}; ; i < ; i++) { ; j < ; ...

  6. Eclipse进行Debug时断点上有一个斜杠,并且debug没有停在断点处

    断点上有斜杠,这是由于设置了Skip All Breakpoints的缘故,调试会忽略所有断点,执行完,只需取消Skip All Breakpoints即可,操作:Run-->Skip All ...

  7. "美团"APP学习记录知识点

    1.APP进入加载广告视图展示: -(void)initAdvView{ // 判断图片是否已经存在 NSArray *paths = NSSearchPathForDirectoriesInDoma ...

  8. oracle增、删、改、查

    参照文档 https://blog.csdn.net/yes_is_ok/article/details/79271965 https://blog.csdn.net/cl723401/article ...

  9. Web测试方法_02

    1.页面链接检查 检查每一个链接是否都有对应的页面,页面与页面之间的来回切换是否正常响应,包括一些返回页面的链接是否正常,还要检查点击图片所链接的页面是否准确展示. 2.相关性检查 功能相关性检查:例 ...

  10. .net代码混淆 .NET Reactor 研究 脚本一键混淆一键发布

    .net代码混淆 .NET Reactor 研究 为什么要混淆? .net比较适合快速开发桌面型应用,但缺点是发布出来的文件是可以反编译的,有时候为了客户的安全,我们的代码或者我们的逻辑不想让别人知道 ...