【问题标题】:QT: Context menu on TriggerQT:触发器上的上下文菜单
【发布时间】:2013-05-08 01:35:25
【问题描述】:

我在 QSystemTrayIcon 中有一个 QMenu。两者都是 QMainWindow 对象的成员。

我希望 QSystemTrayIcon 的 QMenu 在右键单击(即 QSystemTrayIcon::Context 原因)和单击左键时(即 QSystemTrayIcon::Trigger 原因)时的行为完全相同。

默认情况下,右键单击行为就像我想要的那样。但是我不知道如何使左键单击与右键单击完全一样。到目前为止,我的努力使我:

 void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
 {
     if(reason==QSystemTrayIcon::Trigger)  trayIcon->contextMenu()->popup(QCursor::pos());
 }

但是,菜单在失去焦点时不会消失,而右键单击上下文菜单会在失去焦点时使其消失。

有没有办法让触发器像上下文一样?也许是一种抛出模拟信号之类的方法?

【问题讨论】:

    标签: qt event-handling focus system-tray


    【解决方案1】:

    好吧,我需要做同样的事情,但不知道如何用纯 Qt 代码干净地完成它,所以这里有一个适用于 Windows 的小技巧:

    void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
    {
        switch (reason)
        {
        case QSystemTrayIcon::Trigger:
        case QSystemTrayIcon::DoubleClick:
        case QSystemTrayIcon::MiddleClick:
            {
                POINT p;
                GetCursorPos(&p);
                HWND hwnd = WindowFromPoint(p);
                ScreenToClient(hwnd, &p);
                PostMessageA(hwnd, WM_RBUTTONDOWN, MK_RBUTTON, MAKELONG(p.x, p.y));
                PostMessageA(hwnd, WM_RBUTTONUP, 0, MAKELONG(p.x, p.y));
            }
            break;
        case QSystemTrayIcon::Context:
            show();
            setWindowState(windowState() & ~Qt::WindowMinimized | Qt::WindowActive);
            mTrayIcon->contextMenu()->popup(QCursor::pos());
            break;
        default:
            break;
        }
    }
    

    【讨论】:

      【解决方案2】:

      所以,如果我理解正确的话。

      您让 Qt 处理右键(您没有检查插槽中的 Context ),然后菜单在失去焦点时消失。

      但是您正在处理左键点击,您无法获得相同的行为。对吧?

      我至少可以想到两种通过 eventFilter 来做到这一点的方法:

      这将是制造假事件的一种方式。

      bool MainWindow::eventFilter(QObject *obj, QEvent *event){
      if (event->type() == QEvent::MouseButtonPress) {
        QMouseEvent *mEvent = static_cast<QMouseEvent *>(event);
        if(mEvent->button() == Qt::LeftButton)
        {
          QMouseEvent my_event = new QMouseEvent ( mEvent->type(), 
              mEvent->pos(), Qt::Rightbutton , 
          mEvent->buttons(), mEvent->modifiers() );
           QCoreApplication::postEvent ( trayIcon, my_event );
          return true;
        }
      } 
      return QObject::eventFilter(obj, event);
      }
      

      安装

      trayIcon->installEventFilter(this);
      

      从主窗口

      但是,我认为这有点棘手。

      如果你正在制作一个 eventFilter,你可以在菜单上观察 focusOut 事件。

      bool MainWindow::eventFilter(QObject *obj, QEvent *event){
      
        QMouseEvent *mEvent = dynamic_cast<QMouseEvent *>(event);
        if(mEvent)
        {
        if(mEvent->type() == QEvent::Leave || mEvent->type() == QEvent::WindowDeactivate)
        {
          trayIcon->contextMenu()->close();
          return true;
        }
      } 
      return QObject::eventFilter(obj, event);
      }
      

      请注意,我还没有尝试过。不过应该值得一试。

      一些方便的链接:

      How to detect that my application lost focus in Qt?

      installEventFilter

      postEvent

      【讨论】:

      • 你的理解是正确的。在阅读您的示例时,它看起来应该可以工作,但由于某种原因,我的代码中没有触发 eventFilter。
      • 在菜单中安装第二种方法
      • 而 prolly,也在第二种方法中,它是一个 QEvent::MouseMove。我会稍微修改一下代码
      • 其实我还没有尝试过第二种方法。我喜欢第一个,因为它使鼠标左键单击的行为与右键单击完全一样(这是我想要的),而无需将每个行为分配给鼠标左键本身。我将尝试第二种方法,看看会发生什么。
      • 请注意,我没有尝试过代码。也许您必须进行一些调整才能使其正常工作。这只是一个概念证明
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      相关资源
      最近更新 更多