Как получить memfun с двумя параметрами - PullRequest
2 голосов
/ 04 марта 2010

Я хочу использовать эту функцию "EnumWindows (EnumWindowsProc, NULL);". EnumWindowsProc - это функция обратного вызова:

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);

Для этого обратного вызова я хочу использовать функцию-член класса.

Например:

Class MyClass
{
    BOOL CALLBACK My_EnumWindowsProc(HWND hwnd, LPARAM lParam);
    void          test();
};

Итак, я хочу связать вызываемый обратный вызов с моей функцией !!!

Я пытаюсь это:

void MyClass::test()
{
    EnumWindowsProc ptrFunc = mem_fun(&MyClass::My_EnumWindowsProc);
    EnumWindows(ptrFunc, NULL);
}

Это не работает, "mem_fun" может принимать только один аргумент! Возможно ли это сделать? еще вы знаете другое решение? (возможно решение будет возможно с Boost :: bind)

Ответы [ 5 ]

3 голосов
/ 04 марта 2010

Вам необходимо создать Адаптер , например:

#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;
}
0 голосов
/ 12 марта 2013

ребята, Адаптер отлично работал для меня, вот пример моего кода, который я использовал с EnumChildWindow для предварительной автосохранения.

Заголовочный файл:

public:

    BOOL AutosaveTimerChildProc( HWND hwnd );
    static BOOL CALLBACK CallbackAdapter(HWND wnd, LPARAM lp);
...

C ++ файл:

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);
}
0 голосов
/ 04 марта 2010

Не берите в голову мой оригинальный ответ: что вам нужно сделать, это в основном это:

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);
}
0 голосов
/ 04 марта 2010

К сожалению, EnumWindowsProc должен быть статическим, чтобы не добавлять скрытый указатель «this» и делать его несовместимым с прототипом обратного вызова. В прошлом я занимался этим, сохраняя указатель this после создания окна с этим вызовом:

SetWindowLong(handle,GWL_USERDATA,(DWORD)this);

, а затем внутри EnumWindowsProc (который является статическим) сделать что-то вроде этого:

MyClass* thisClass = (MyClass*)GetWindowLong(hwnd,GWL_USERDATA);

и теперь у вас есть указатель на объект. Вы можете использовать это для вызова нестатической функции:

thisClass->ActualEnumWindowsProc(hwnd,lParam);
0 голосов
/ 04 марта 2010

посмотрите, нестатические методы каждого класса имеют еще один скрытый параметр (первый) this, который является указателем на экземпляр класса. так что думайте, что настоящая подпись это:

BOOL CALLBACK My_EnumWindowsProc(MyClass* this, HWND hwnd, LPARAM lParam);

теперь понятнее? это означает, что вы не можете использовать его в этом контексте

...