C++ 在单独的类上设置WinEvent

C++ 在单独的类上设置WinEvent,c++,qt,C++,Qt,我对Qt有点问题,下面是我的代码: SessionSnatcher.h: #ifndef SESSIONSNATCHER_H #define SESSIONSNATCHER_H #include <Windows.h> #include <QThread> #include <QtCore> #include <QDebug> class SessionSnatcher : public QThread { public: Sessi

我对Qt有点问题,下面是我的代码:

SessionSnatcher.h:

#ifndef SESSIONSNATCHER_H
#define SESSIONSNATCHER_H

#include <Windows.h>
#include <QThread>
#include <QtCore>
#include <QDebug>


class SessionSnatcher : public QThread
{
public:
    SessionSnatcher();
    ~SessionSnatcher();
    void run();
    void SetPID(int pid);
    void SetTID(int tid);
    int GetPID();
    int GetTID();
    HWND GetCOProductControl();

private:

    //HWND GetCOProductControl();
    void CALLBACK SessionSnatcher::handler(HWINEVENTHOOK hook , DWORD event , LONG idChild , LONG idObject , DWORD dwEventThread , DWORD dwmsEventTime);
    HWINEVENTHOOK hook;
    int PID , TID;

};

#endif // SESSIONSNATCHER_H
现在我不断地发现这个错误:

D:\TT\sessionsnatcher.cpp:25: error: C2664: 'HWINEVENTHOOK SetWinEventHook(DWORD,DWORD,HMODULE,WINEVENTPROC,DWORD,DWORD,DWORD)' : cannot convert argument 4 from 'void (__stdcall SessionSnatcher::* )(HWINEVENTHOOK,DWORD,LONG,LONG,DWORD,DWORD)' to 'WINEVENTPROC'
There is no context in which this conversion is possible
在此之前,我使用的是“handler”而不是“&SessionSnatcher::handler”,但我有一个问题,就是说它是一个成员,不能这样使用。 现在我想不出来了。 当我尝试它时,它在VisualStudio上运行得很好,我所要做的就是像(WINEVENTPROC)处理程序一样进行强制转换,但我认为因为我使用的是单独的类,所以我不能再这样做了


有什么提示吗?

您已经成为每个非静态类方法中隐藏的
这个
参数的牺牲品。一个现代的解决方案是使用,但这将帮助你没有C + API或C++ API,它比C++ 11早。p>
当
std::bind
不可用时,典型的解决方案是使用

  • 满足您需要提供的原型
  • 将回调映射到对象,然后
  • 对在2中找到的对象调用所需的方法
  • 通常Win32 API调用都有一个指向用户参数的指针,您可以使用它来简化操作:只需将指针强制转换为
    SessionSnatcher*
    ,然后调用该函数。我在
    WinEventProc
    的参数列表中看不到用户参数,因此您必须创造性地映射其中一个事件ID或句柄
    WinEventProc
    提供并唯一地标识
    SessionSnatcher

    或者,如果您只有一个
    SessionSnatcher
    ,则可以编写函数以始终使用该
    SessionSnatcher

    以下是一个通用示例:

    #include <iostream>
    #include <map>
    
    typedef int (*funcp)(int id, int p1, int p2);
    // using typedef instead of using on purpose because that's what'll be in
    // the Windows API
    
    class test
    {
    private:
        static std::map<int, test*> tests; // our map of id -> test objects
        int id; // this test's id. Only included for proof
    public:
        test(int id):id(id)
        {
            tests[id] = this; // put in map. In the real world test for collision first
        }
    
        // function that will eventually be called
        int func(int p1, int p2)
        {
            (void) p1;
            (void) p2;
            std::cout << "Called func for " << id << std::endl;
            return 0;
        }
    
        // static method that can be called by API
        static int staticfunc(int id, int p1, int p2)
        {
            // look up object and call non-static method
            // I recommend at() instead of [] because you get a catchable exception
            // rather than a crash over null pointer if id is unknown.
            return tests.at(id)->func(p1, p2);
        }
    };
    
    // allocating storage for static map
    std::map<int, test*> test::tests;
    
    // function mocking up API. Takes a function and an identifier used by called function
    int caller(funcp func,
               int id)
    {
        return func(id, 100, 20); // just calls the function
    }
    
    // tester
    int main(void)
    {
        test a(1); // create a test
        test b(2); // create a test
    
        try
        {
            caller(test::staticfunc, 2); // call test 2 through API
            caller(test::staticfunc, 1); // call test 1 through API
            caller(test::staticfunc, 10); // throw exception over unknown id
        }
        catch (std::exception &e)
        {
            std::cout << "Failed call: " << e.what() << std::endl;
        }
    }
    

    “map::at”不是什么异常消息,但它可以转换为有用的日志消息。无论如何,它胜过了没有信息的segfault。

    谢谢你的回答,我尝试过使用一个免费函数进行回调(我希望这就是你的意思),但我还是遇到了同样的错误!但是它与原始的
    处理程序
    函数一起工作,是吗?当前
    SessionSnatcher::handler
    似乎缺少
    WinEventProc
    的第三个参数:
    HWND-HWND
    。同时缺少此参数的自由函数将生成完全相同的错误消息。很抱歉,我之前没有发现。你知道我刚刚尝试从处理程序中删除(WINEVENTPROC),但仍然得到一个错误,顺便说一句,我注意到我从处理程序回调中漏掉了HWND的参数,我不知道我怎么漏掉了它!当前错误:
    sessionsnatcher.obj:-1:错误:LNK2019:未解析的外部符号\uu imp__SetWinEventHook@28在函数“public:virtualvoid\uu thiscall SessionSnatcher::run(void)”中引用(?run@SessionSnatcher@@UAEXXZ)
    您是否已将
    User32
    添加到项目->属性->配置属性->链接器->输入->其他依赖项?哇!虽然这是我经常做的第一件事,但这次我忘了!就这样,只需
    LIBS+=-luser32
    解决了它。谢谢你的帮助@user4581301
    #include <iostream>
    #include <map>
    
    typedef int (*funcp)(int id, int p1, int p2);
    // using typedef instead of using on purpose because that's what'll be in
    // the Windows API
    
    class test
    {
    private:
        static std::map<int, test*> tests; // our map of id -> test objects
        int id; // this test's id. Only included for proof
    public:
        test(int id):id(id)
        {
            tests[id] = this; // put in map. In the real world test for collision first
        }
    
        // function that will eventually be called
        int func(int p1, int p2)
        {
            (void) p1;
            (void) p2;
            std::cout << "Called func for " << id << std::endl;
            return 0;
        }
    
        // static method that can be called by API
        static int staticfunc(int id, int p1, int p2)
        {
            // look up object and call non-static method
            // I recommend at() instead of [] because you get a catchable exception
            // rather than a crash over null pointer if id is unknown.
            return tests.at(id)->func(p1, p2);
        }
    };
    
    // allocating storage for static map
    std::map<int, test*> test::tests;
    
    // function mocking up API. Takes a function and an identifier used by called function
    int caller(funcp func,
               int id)
    {
        return func(id, 100, 20); // just calls the function
    }
    
    // tester
    int main(void)
    {
        test a(1); // create a test
        test b(2); // create a test
    
        try
        {
            caller(test::staticfunc, 2); // call test 2 through API
            caller(test::staticfunc, 1); // call test 1 through API
            caller(test::staticfunc, 10); // throw exception over unknown id
        }
        catch (std::exception &e)
        {
            std::cout << "Failed call: " << e.what() << std::endl;
        }
    }
    
    Called func for 2
    Called func for 1
    Failed call: map::at