Search code examples
c++qtui-automationmicrosoft-ui-automationmouse-hook

how to access ui structures(textboxes,labels) inside static function MouseProc, SetWindowsHookEx?


In my .h file function mouseProc is declared as static(it has to be)

.h file

static LRESULT CALLBACK mouseProc(int Code, WPARAM wParam, LPARAM lParam);

initially i thought i would add &ui as a parameter to this function, but i am not able to do so. it gives me error "incompatible parameter type with HOOKPROC"

so, now i am not able to access the textboxes and labels in my UI by using
ui->textbox->apped(); how to solve this ?

---UPDATE as per suggestion of making ui static--------------

mainwindow.h

#pragma once
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "windows.h"
#include "windowsx.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT                      //Used to handle events
    Q_DISABLE_COPY(MainWindow) //added

public:
    MainWindow(QWidget* parent = 0);
    ~MainWindow();                    //Destructor used to free resources

    // Static method that will act as a callback-function
   static LRESULT CALLBACK mouseProc(int Code, WPARAM wParam, LPARAM lParam);

 //   BOOL InitializeUIAutomation(IUIAutomation** automation);

  static Ui::MainWindow* ui; // declared static,pointing to UI class

private:

    // hook handler
    HHOOK mouseHook;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <Windows.h>
#include <UIAutomation.h>

using namespace std;

Ui::MainWindow* MainWindow::ui = 0;

MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
    //, ui(new Ui::MainWindow)
{
    ui = new Ui::MainWindow();
    ui->setupUi(this);

    
     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";
    }
}
BOOL InitializeUIAutomation(IUIAutomation** automation)
{
    CoInitialize(NULL);
    HRESULT hr = CoCreateInstance(__uuidof(CUIAutomation), NULL,
        CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation),
        (void**)automation);
    return (SUCCEEDED(hr));
}

MainWindow::~MainWindow()
{
    delete ui;
}
LRESULT CALLBACK MainWindow::mouseProc(int Code, WPARAM wParam, LPARAM lParam)
{
    ui->textbox->append(string);
}

Solution

  • You can't add extra parameters to mouseProc. The compiler won't accept it, it needs to match the signature that SetWindowsHookEx() is expecting. If you resort to using a type-cast to force the compiler to accept it, the OS still won't know how to populate the new parameters with values at runtime when the hook is called, and you will just end up corrupting the call stack, and/or crashing your code.

    To do what you want, you will simply have to store your ui pointer in global memory, or even make it be static as well. Somewhere that mouseProc can reach it.

    As for the compiler error, what it says is correct - the MainWindow class you have shown does not have a member named textbox, which is why accessing ui->textbox (regardless of where ui will come from) fails to compile. So, you need to figure out where the textbox is really being stored, and then access it from THERE instead of from the MainWindow.