I have a little problem with Qt , here is my code :
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;
}
And now i keep getting this error :
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
Before this i was using "handler" instead of "&SessionSnatcher::handler" but i had a problem saying it was a member and it cant be used like that. Now i cant work it out. It worked well on Visual Studio When i tried it , all i had to do was cast like (WINEVENTPROC)handler , but i think since im using a separate class i cant do that anymore.
Any tips ?
You have fallen victim to the hidden this parameter in every non-static class methods. A modern solution is to use std::bind, but that won't help you with a C-based API or a C++ API that predates C++11.
The typical solution when std::bind isn't available is a free function or static method that
Often Win32 API calls have a pointer to a user argument you can use to make this easy: just cast the pointer to SessionSnatcher * and call the function. I don't see a user argument in WinEventProc's parameter list, so you'll have to get creative and map one of the event ids or handles WinEventProc does provide and uniquely identifies a SessionSnatcher.
Or if you only have one SessionSnatcher you can write the function to always use that one SessionSnatcher.
Here is a generic example:
#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;
}
}
Typical output:
Called func for 2
Called func for 1
Failed call: map::at
"map::at" isn't much of an exception message, but it can be converted into a useful log message. At any rate it beats a segfault with no information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With