Jaguar
Jaguar

Reputation: 339

How to have memfun with two parameters

I want to use this function "EnumWindows(EnumWindowsProc, NULL);". The EnumWindowsProc is a 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)

Upvotes: 2

Views: 896

Answers (5)

Ryan
Ryan

Reputation: 1

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);
}

Upvotes: 0

Jan
Jan

Reputation: 1847

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);
}

Upvotes: 0

Cthutu
Cthutu

Reputation: 8917

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);

Upvotes: 0

John Dibling
John Dibling

Reputation: 101506

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;
}

Upvotes: 3

Andrey
Andrey

Reputation: 60105

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

Upvotes: -1

Related Questions