4

友人、Windows API のラッパーを実装しようとしていて、親ウィンドウから子ウィンドウ イベントをキャプチャしたいので、簡単なイベント ハンドラーを作成しました。関数ポインターを使用して、コールバック関数を格納しました。私は静的関数でそれをしました。以下のコードを参照してください。

class Widget;
typedef void (*EventProc)(MSG* EventArgs);
class Widget
{
public:
    /// Constructors destructor and methods for Registering and Creating Windows
    static LRESULT CALLBACK MainProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
    {
        MSG struct_msg;
        struct_msg.hWnd=hWnd;
        struct_msg.message=msg;
        struct_msg.wParam=wParam;
        struct_msg.lParam=lParam;

        Widget* wid=(Widget*)GetWidgetPointerFromHWND(hWnd);

        switch(msg)
        {
            case WM_CREATE:
                if(Created!=NULL)
                    (*(wid->Created))(&struct_msg);break;
            case WM_DESTROY:
                if(Destroyed!=NULL)
                    (*(wid->Destroyed))(&struct_msg);break;
            default:
                return DefWindowProc(hWnd,msg,wParam,lParam);
        }
        return 0;
    }
    EventProc Created;
    EventProc Destroyed;

};

class CustomControl: public Widget
{
    /// Constructor destructor and other methods

};

class Window: public Widget
{
public:

    static void ChildCreated(Widget* Sender,Widget* Self,MSG* EventArgs)
    {
        MessageBox(0,0,0,0);
    }

    Window()
    {
        control1=new CustomControl(100,100,200,200); //left,top,width,height
        this->AddChild(control1);
        control1->Created = ChildCreated; 
    }
private:
    CustomControl control1;
};

これは機能しますが、静的関数にはこのポインターがないため、クラス Windowの変数とメンバー関数にアクセスできませんでした。コールバック関数(Event Handler)としてメンバ関数を作りたいです。私が解決しようとしていることを理解していただければ幸いです。私を助けてください。

4

1 に答える 1

1

この例で示した主なアイデアは正しいです。

クラスにマップする関数static WndProcとマッピングを作成します。HWND

ウィジェットの新しいインスタンスを作成するときは、それをマッピングに追加します。破壊すると、マッピングから削除されます。

WndProc 関数では、マッピングからクラスのインスタンスを取得し、そのインスタンスの仮想イベント ハンドラー関数を呼び出します。

class WidgetBase
{
public:
    WidgetBase()
    {
        _handle = CreateWindow(/*...*/, &WidgetBase::MainProc, /*...*/);
        _widgets.insert(std::make_pair(handle, this);
    }
    virtual ~WidgetsBase() 
    {
       _widgets.remove(handle);
    }
protected:
    HWND _handle;
    virtual LRESULT handleEvents(UINT msg,WPARAM wParam,LPARAM lParam)
    {
         return DefWindowProc(_handle, hWnd,msg,wParam,lParam);
    }
private:
    static std::map<HWND, WidgetBase*> _widgets;

    static WidgetBase* GetWidgetPointerFromHWND(HWND handle)
    {
        // some error handling should be put there
        return _widgets[handle];
    }

    static LRESULT CALLBACK MainProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
    {
        WidgetBase* wid=GetWidgetPointerFromHWND(hWnd);
        if (wid) {
            return wid->handleEvents(msg, wParam, lParam);
        }
        else {
            return DefWindowProc(hWnd,msg,wParam,lParam);
        }
    }
};
std::map<HWND, WidgetBase*> WidgetBase::_widgets;

handleEvents次に、派生クラスで関数をオーバーライドするだけです。

class Derived: public WidgetBase
{
protected:
virtual LRESULT handleEvents(UINT msg,WPARAM wParam,LPARAM lParam)
    {
         // This is your event handler, that is memeber function
         //...
         return WidgetBase::handleEvents(msg, wParam, lParam);
    }
};
于 2012-11-18T19:17:23.933 に答える