I want to use this function "EnumWindows(EnumWindowsProc, NULL);". The EnumWindowsProc is a 开发者_StackOverflow社区Callback function:
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
For this callback I want to use a member function of a class.
e.g:
Class MyClass
{
BOOL CALLBACK My_EnumWindowsProc(HWND hwnd, LPARAM lParam);
void test();
};
So i want to bind the called Callback with my function !!!
I try this:
void MyClass::test()
{
EnumWindowsProc ptrFunc = mem_fun(&MyClass::My_EnumWindowsProc);
EnumWindows(ptrFunc, NULL);
}
It's doesn't work, "mem_fun" can take only one argument ! Is it possible to do that ? else do you know another solution ? (maybe a solution will be possible with Boost::bind)
You need to create an Adapter, such as:
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
class MyCallback
{
public:
MyCallback() : count_(0) {};
static BOOL CALLBACK CallbackAdapter(HWND, LPARAM);
BOOL Callback(HWND);
unsigned count_;
};
BOOL MyCallback::Callback(HWND wnd)
{
char title[1025] = {};
GetWindowText(wnd, title, sizeof(title)-1);
cout << wnd << "= '" << title << "'" << endl;
++count_;
return TRUE;
}
BOOL MyCallback::CallbackAdapter(HWND wnd, LPARAM lp)
{
MyCallback* that = reinterpret_cast<MyCallback*>(lp);
return that->Callback(wnd);
}
int main()
{
MyCallback cb;
EnumWindows(&MyCallback::CallbackAdapter, reinterpret_cast<LPARAM>(&cb));
cout << "Windows Found: " << cb.count_;
return 0;
}
Unfortunately EnumWindowsProc needs to be static to avoid adding the hidden "this" pointer and making it incompatible with the callback prototype. I've handled this in the past by saving the this pointer after creation of the window with this call:
SetWindowLong(handle,GWL_USERDATA,(DWORD)this);
and then inside the EnumWindowsProc (which is static) do something like this:
MyClass* thisClass = (MyClass*)GetWindowLong(hwnd,GWL_USERDATA);
and now you have the object pointer. You could use this to call a non-static function:
thisClass->ActualEnumWindowsProc(hwnd,lParam);
Nevermind my original answer: what you need to do is basically this:
struct InfoINeed {
MyClass * mThis;
...
};
BOOL MyCallback(HWND hwnd, LPARAM lParam) {
InfoINeed* info = (InfoINeed*)hwnd;
// do your stuff, i.e. info->mThis->MyImplementationForCallback(lParam)
// note that you won't need to pass hwnd further, it's a pointer to your own context
}
void MyClass::test()
{
InfoINeed Info = {this, ...};
EnumWindows(MyCallback, &Info);
}
guys the Adapter worked great for me, here is a sample of my code, which I was using with a EnumChildWindow to preform an AutoSave.
Header file:
public:
BOOL AutosaveTimerChildProc( HWND hwnd );
static BOOL CALLBACK CallbackAdapter(HWND wnd, LPARAM lp);
...
C++ file:
BOOL CMainFrame::InitInstance()
{
SetTimer(0, 5 * 60 * 1000,NULL);
return TRUE;
}
void CMainFrame::OnTimer(UINT nIDEvent)
{
::EnumChildWindows(m_hWnd,&CMainFrame::CallbackAdapter,NULL);
}
BOOL CMainFrame::AutosaveTimerChildProc(HWND hwnd)
{
if(DYNAMIC_DOWNCAST(CVISIONView,CWnd::FromHandle(hwnd)) != NULL)
{
::PostMessage(hwnd,WM_MYVIEW_AUTOSAVETIMER,0,0);
}
return TRUE;
}
BOOL CMainFrame::CallbackAdapter(HWND wnd, LPARAM lp)
{
CMainFrame* that = reinterpret_cast<CMainFrame*>(lp);
return that->AutosaveTimerChildProc(wnd);
}
look, non static methods of every class has one more hidden parameter (first one) this
which is pointer to instance of class. so think that real signature is:
BOOL CALLBACK My_EnumWindowsProc(MyClass* this, HWND hwnd, LPARAM lParam);
is it clearer now? it means that you can't use it in this context
精彩评论