c++ - 在单独的类上设置 WinEvent

标签 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:
    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

session 捕捉器.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

在此之前,我使用的是“handler”而不是“&SessionSnatcher::handler”,但我说它是成员时遇到了问题,不能那样使用。 现在我无法解决。 它在 Visual Studio 上运行良好当我尝试它时,我所要做的就是像 (WINEVENTPROC)handler 一样进行转换,但我认为自从我使用单独的类以来我不能再这样做了。

有什么建议吗?

最佳答案

您已经成为每个非静态类方法中隐藏的 this 参数的牺牲品。现代解决方案是使用 std::bind ,但这对基于 C 的 API 或早于 C++11 的 C++ API 没有帮助。

std::bind 不可用时的典型解决方案是 free function或静态方法

  1. 满足您需要提供的原型(prototype),
  2. 将回调映射到对象,并且
  3. 对在 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;
    }
}

典型输出:

Called func for 2
Called func for 1
Failed call: map::at

“map::at”不是异常消息,但它可以转换为有用的日志消息。无论如何,它在没有任何信息的情况下击败了一个段错误。

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

相关文章:

c++ - Windows Embedded Compact(Windows CE)程序的事后分析

c++ - dyld : Library not loaded: libqscintilla2. 5.dylib

qt - 如何将项目添加到布局中的特定索引

c++ - 一次又一次地获得相同的内存

c++ - 如何将 Eigen::Matrix4f 转换为 Eigen::Affine3f

c++ - error C2512 没有合适的默认构造函数可用

macos - QT Creator 构建期间未创建 Moc 文件

c++ - 纯虚函数声明中的 `= 0`是什么意思?

c++ - 在 linux 中使用 opencv 从 windows 共享文件夹中读取图像

c++ - QSystemTrayIcon激活信号: DoubleClick without Trigger