2012-06-22 42 views
0

我在我的項目設置中有一個窗口的構造函數,使它看起來像這樣。我的項目中有很多窗口,我經常添加或刪除東西。預處理器宏自動生成窗口消息循環

LRESULT CPicture::Msg(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(uMsg) 
    { 
     HANDLE_MSG(hWnd, WM_CREATE, OnCreate); 
     HANDLE_MSG(hWnd, WM_PAINT, OnPaint); 
     HANDLE_MSG(hWnd, WM_SIZE, OnSize); 
     HANDLE_MSG(hWnd, WM_CLOSE, OnDestroy); 

     default: 
      return (DefWindowProc(hWnd, uMsg, wParam, lParam)); 
    } 
} 

下面是所有有效事件的示例;

// Csx/Dsx 
virtual BOOL OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct) {return FALSE;}; 
virtual void OnDestroy(HWND hWnd){}; 

// Painting 
virtual void OnPaint(HWND hWnd){}; 
virtual BOOL OnEraseBkgnd(HWND hWnd, HDC hDC) {return FALSE;}; 

// Movement/Sizing 
virtual void OnMove(HWND hWnd, int x, int y) {}; 
virtual void OnSize(HWND hWnd, UINT state, int nWidth, int nHeight){}; 
virtual void OnGetMinMaxInfo(HWND hWnd, LPMINMAXINFO lpMinMaxInfo){}; 

// Focus 
virtual void OnSetFocus(HWND hWnd, HWND hWndOldFocus){}; 
virtual void OnKillFocus(HWND hWnd, HWND hWndNewFocus){}; 

...還有很多。是否有可能使用預處理器宏來檢測何時在子類中重寫了其中一個函數,並自動爲它添加一個處理程序給消息循環?

有人告訴我,即使它沒有定義,我的Msg()處理每一條消息都是一個非常糟糕的主意,所以我正在尋找一個簡單的替代方案,它不會在用戶不斷增加/刪除事件定義。

+0

使用C++,不會使用通用基類和虛函數是一個明顯的想法嗎? –

回答

1

這是不可能的你想要的是使用標準的預處理程序,但下面的博·佩爾鬆的評論做,你可以做這樣的事情:

class MessageHandler 
{ 
public: 
    virtual void Handle() = 0; 
    static void Dispatch (int i) { m_messages [i]->Handle(); } 
protected: 
    MessageHandler (int i) { m_messages [i] = this; } 
private: 
    static map <int, MessageHandler *> m_messages; 
}; 

map <int, MessageHandler *> MessageHandler::m_messages; 

template <int i> 
class MessageHandlerInstance : MessageHandler 
{ 
protected: 
    MessageHandlerInstance() : MessageHandler (i) { } 
}; 

#define Handler(name,i) class name : public MessageHandlerInstance <i> { void Handle(); } name##Instance; 

// these are the actual handlers for the messages 
Handler (Msg1, 1); 
void Msg1::Handle() { cout << "Msg1" << endl; } 

Handler (Msg2, 2); 
void Msg2::Handle() { cout << "Msg2" << endl; } 

Handler (Msg3, 3); 
void Msg3::Handle() { cout << "Msg3" << endl; } 


int main() 
{ 
    // and this is how they're called 
    MessageHandler::Dispatch (1); 
    MessageHandler::Dispatch (2); 
    MessageHandler::Dispatch (3); 
} 

它需要一些錯誤檢查 - 調度呼叫會如果沒有定義消息處理程序,則失敗。另外,你可以將模板類移入#define,但這會使#define變大。

+0

很好的回答它的完美。你能建議我確定消息處理程序的最佳方式嗎?可以使用矢量而不是數組嗎? – kvanberendonck

+0

@kvanberendonck:它使用std :: map,因此您可以使用std :: map :: find而不是[]並更改Dispatch方法以返回發現/未找到的消息處理程序的真/假(或不' t傳給父母/傳給父母)。 – Skizz

+0

謝謝!那很完美!! – kvanberendonck