我对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

SessionSnatcher.cpp:
#include "sessionsnatcher.h"

SessionSnatcher::SessionSnatcher()
{

}

SessionSnatcher::~SessionSnatcher()
{
    UnhookWinEvent(hook);
}

void CALLBACK SessionSnatcher::handler(HWINEVENTHOOK hook , DWORD event , LONG idChild , LONG idObject , DWORD dwEventThread , DWORD dwmsEventTime)
{

}

void SessionSnatcher::run()
{
    hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND , EVENT_SYSTEM_FOREGROUND , NULL , &SessionSnatcher::handler , PID , TID , WINEVENT_OUTOFCONTEXT);
}



HWND SessionSnatcher::GetCOProductControl()
{
    HWND TPanel = FindWindow(L"TPanel" , NULL);
    return TPanel;
}

void SessionSnatcher::SetPID(int pid)
{
    PID = pid;
}

void SessionSnatcher::SetTID(int tid)
{
    TID = tid;
}

int SessionSnatcher::GetPID()
{
    return PID;
}

int SessionSnatcher::GetTID()
{
    return TID;
}

现在我不断收到此错误:
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

在此之前,我使用的是“处理程序”,而不是“&SessionSnatcher::handler”,但我有一个问题,说它是一个成员,因此不能像这样使用。
现在我无法解决。
它在Visual Studio上运行良好,当我尝试使用它时,我要做的一切都像(WINEVENTPROC)handler一样,但是我认为由于IM使用单独的类,因此我无法再这样做了。

有小费吗 ?

最佳答案

您已成为每种非静态类方法中隐藏的this参数的受害者。一个现代的解决方案是使用 std::bind ,但是使用基于C的API或早于C++ 11的C++ API不会帮到您。
std::bind不可用时的典型解决方案是free function或静态方法

  • 符合您需要提供的原型(prototype)
  • 将回调映射到对象,然后
  • 对2中找到的对象调用所需的方法。

  • 通常,Win32 API调用具有指向用户参数的指针,您可以使用该参数来简化此过程:只需将指针转换为SessionSnatcher *并调用该函数即可。我没有在WinEventProc的参数列表中看到用户参数,因此您必须具有创造力,并映射WinEventProc确实提供的事件ID或句柄之一,并唯一标识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;
        }
    }
    

    典型输出:
    Called func for 2
    Called func for 1
    Failed call: map::at
    

    “map::at”并不是什么异常消息,但是可以将其转换为有用的日志消息。无论如何,它击败了没有信息的段错误。

    关于c++ - 在单独的类上的SetWinEvent,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37758716/

    10-08 20:42