2012-11-18 12 views
4

朋友,我試圖實現Windows API的包裝,並且我想從父窗口捕獲子窗口事件,所以我做了一個簡單的事件處理程序。我使用函數指針來存儲回調函數。我用靜態函數做了它。請參閱下面的代碼。嘗試實現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; 
}; 

這工作,但由於可是沒有這個指針的靜態函數,我無法訪問的類窗口變量和成員函數。 我想將一個成員函數作爲回調函數(Event Handler)。 我希望你明白我想要解決的問題。請幫幫我。

+0

如果你從'GetWidgetPointerFromHWND'獲得'Widget'的實例,你可以訪問它的變量和成員。那麼,什麼是錯的? – Lol4t0

+0

@ Lol4t0我想將Window的非靜態成員函數作爲事件處理函數。 – user1833918

+0

但是,只要你得到'wid',你可以調用它的函數,如'wid-> handleEvent(msg,wParam,lParam)'。對? – Lol4t0

回答

1

你在這個例子中顯示的主要想法是正確的。

您製作了一些staticWndProc函數和映射,即將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); 
    } 
}; 
相關問題