Mouse event singleton Question.



  • Hi i'm trying to do with singleton one program to show mouse events. But i want sometimes stop this hook so i need use this sentence:

    UnhookWindowsHookEx(mouseHook);
    

    But i'm little lost and i dont know how to add to my code;

    Code.h file:

    #ifndef MOUSELOGGER_H
    #define MOUSELOGGER_H
     
    #include <QObject>
    #include <windows.h>
     
    class MouseLogger : public QObject
    {
        Q_OBJECT
        Q_DISABLE_COPY(MouseLogger)
    public:
        static MouseLogger &instance();
        explicit MouseLogger(QObject *parent = nullptr);
        virtual ~MouseLogger(){}
     
        // Static method that will act as a callback-function   
        static LRESULT CALLBACK mouseProc(int Code, WPARAM wParam, LPARAM lParam);
     
    signals:
        // The signal, which will report the occurrence of an event
        void mouseEvent();
     
    public slots:
     
    private:
        // hook handler
        HHOOK   mouseHook;
    };
     
    #endif // MOUSELOGGER_H
    

    Code.cpp:

    #include "mouselogger.h"
    #include <QDebug>
     
    MouseLogger &MouseLogger::instance()
    {
        static MouseLogger _instance;
        return _instance;
    }
     
    MouseLogger::MouseLogger(QObject *parent) : QObject(parent)
    {
        HINSTANCE hInstance = GetModuleHandle(NULL);
     
        // Set hook
        mouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, hInstance, 0);
        // Check hook is correctly
        if (mouseHook == NULL) {
            qWarning() << "Mouse Hook failed";
        }
    }
     
    LRESULT CALLBACK MouseLogger::mouseProc(int Code, WPARAM wParam, LPARAM lParam)
    {
        Q_UNUSED(Code)
     
        // Having an event hook, we nned to cast argument lParam 
        // to the structure of the mouse is the hook.
        MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lParam;
     
        // Next, we check to see what kind of event occurred, 
        // if the structure is not a pointer to nullptr
        if(pMouseStruct != nullptr) {
            switch (wParam) {
            case WM_MOUSEMOVE:
                qDebug() << "WM_MOUSEMOVE";
                break;
            case WM_LBUTTONDOWN:
                qDebug() << "WM_LBUTTONDOWN";
                break;
            case WM_LBUTTONUP:
                qDebug() << "WM_LBUTTONUP";
                break;
            case WM_RBUTTONDOWN:
                qDebug() << "WM_RBUTTONDOWN";
                break;
            case WM_RBUTTONUP:
                qDebug() << "WM_RBUTTONUP";
                break;
            case WM_MBUTTONDOWN:
                qDebug() << "WM_MBUTTONDOWN";
                break;
            case WM_MBUTTONUP:
                qDebug() << "WM_MBUTTONUP";
                break;
            case WM_MOUSEWHEEL:
                qDebug() << "WM_MOUSEWHEEL";
                break;
            default:
                break;
            }
            emit instance().mouseEvent();
        }
     
        // After that you need to return back to the chain hook event handlers
        return CallNextHookEx(NULL, Code, wParam, lParam);
    }
    

    Main function where i want to deactivate this hook:

    #include <QCoreApplication>
    #include <QDebug>
    #include "mouselogger.h"
     
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
     
        QObject::connect(&MouseLogger::instance(), &MouseLogger::mouseEvent,
                         [](){
            qDebug() << "Mouse Event";
        });
     
        return a.exec();
    }
    

  • Qt Champions 2016

    hi
    you should/could make a function of our class
    like stoplogging()

    and there call
    UnhookWindowsHookEx(mouseHook);

    so in main , you can say

    MouseLogger::instance().stoplogging();



  • @mrjj the member must be static?



  • @mrjj Ok worked but i have some questions why sometimes it's useful use static method? What is the utility? If for example i want to include one signal and slot i need to do the same?
    It's useful to use qobject when and why.
    thx overall i use in databases and events games.


  • Qt Champions 2016

    @Jeronimo
    No need to make it static as you call via an instance.
    You use static function to be able to call them WITHOUT an instance.

    Signals and slots have notning to do with static use.

    Example:

    Say we have class Printer and it has a name() function.

    If NOT static we must do
    Printer myp; // instance
    myp.name();

    if we make it static, its a not needed
    you can say
    Printer::name(); // to call it with no instance.

    Qt Example is
    QFileDialog::getOpenFileName(this,
    tr("Open Image"), "/home/jana", tr("Image Files (*.png *.jpg *.bmp)"));

    here we use a static getOpenFileName without an instance of QFileDialog

    So static is good for utility functions but should NOT be used a lot.


  • Qt Champions 2016

    @Jeronimo
    Oh, the reason for
    static LRESULT CALLBACK mouseProc(int Code, WPARAM wParam, LPARAM lParam);
    is static here is that Windows cannot get an instance of an Object to call so it has to be plain function or
    a static function for it to call it back.

    So the reason for static here , is that the callback CANNOT live as normal function in a class and be called from outside
    from code that cannot know class types. (from your app)



  • @mrjj Ok thx one little question if i connect the instance with qobject::connect is necessary or not?¿ because it's very using too sorry to late .


  • Qt Champions 2016

    @Jeronimo said in Mouse event singleton Question.:

    i connect the instance with qobject::connect is necessary or not?

    Its not necessary for the call back ?
    but if you want MouseLogger to emit signal , then yes you must use the Instance to connect.
    Connect need a real object and cannot use static member functions.



  • @mrjj But if for example i want to use signals and slots:
    connect(MouseLogger::Instance(),SIGNAL(testSignal()), this,SLOT(testSlot()));

    I can include this code to my program to use different signal and slots? but i' dont know how.

    When you say this:
    Signals and slots have notning to do with static use.

    So i dont need to use static functions for this.


  • Qt Champions 2016

    @Jeronimo
    Yes that would be the way, but one note
    connect(MouseLogger::Instance(),SIGNAL(testSignal()), this,SLOT(testSlot()));

    When you are in main, there is no this pointer. That have to be inside a class, say mainwindow.

    So you would have to use the new syntax and a lambda as you already did with
    QObject::connect(&MouseLogger::instance(), &MouseLogger::mouseEvent,
    {
    qDebug() << "Mouse Event";
    });

    The []() makes it the lamba thing and then you dont need another instance of a class for the THIS part.
    Remember what we say is
    connect( some instance, that signal, to this other/same instance, to this slot (function)

    But the c+11 feature called lambda makes it possible to create function RIGHT there so to speak
    and can be used in main - to add slots that can respond (in main) to your Logger.

    A common design is called Producers / Consumers and it would not be a bad design
    if anyone using the Logger would be another class ( and not main) as
    it's very flexible as you can then just swap the Consumer (main) with some other
    consumer and do other stuff. Or have mutiple consumers to same Producer (logger).
    This is vastly simplified version of the design. so take it as "overall" concept.
    https://dzone.com/articles/producer-consumer-pattern

    Final note is:
    Always/please do
    qDebug << "con1:" << connect(xxx);
    when using the SLOT() , SIGNAL() version and check it says "true" in Application output.
    Its very helpful and takes the guessing away :)



  • This post is deleted!

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.