Search code examples
qtuser-interfacecallbackqtgui

Accessing QT GUI from CALLBACK


I am catching all mouse events happening in my program with a windows hook:

#include <Windows.h>
#pragma comment(lib, "user32.lib")
HHOOK hHook = NULL;
using namespace std;

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {   
    switch( wParam )
    {
      case 0x201:  qDebug() << "Left click"; // Left click
    }
    return CallNextHookEx(hHook, nCode, wParam, lParam);
}

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
hHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, NULL, 0);
if (hHook == NULL) {
    qDebug() << "Hook failed";
}
ui->setupUi(this);
}

I want to put the data received inside MouseProc() into a label on my QT GUI. How can I access it from there? This for example doesn't work:

ui->label1->setText("Left click");

Solution

  • First of all I would add new function to your MainWindow class, that will return the pointer to the label you want to update:

    QLabel *MainWindow::label() const
    {
        return ui->label1;
    }
    

    and than I would rewrite the callback function in the following way:

    LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {   
        switch( wParam )
        {
            case 0x201:
                qDebug() << "Left click"; // Left click
                QWidgetList wl = QApplication::topLevelWidgets ();
                foreach (QWidget *widget, wl) {
                    if (MainWindow *mw = qobject_cast<MainWindow *>(widget)) {
                        mw->label()->setText("Left click");
                        break;
                    }
                }
        }
        return CallNextHookEx(hHook, nCode, wParam, lParam);
    }
    

    Alternatively, of course, you can use global variables etc., but I find this solution much more elegant.

    UPDATE:

    Another improvement, that looks even better to me, is just hiding the label information and update mouse click status with such function:

    void MainWindow::setMouseStatus(const QString &text)
    {
        ui->label1->setText(text);
    }
    

    Now you can call it from the callback as:

    [..]
    mw->setMouseStatus("Left click");