2012-06-22 46 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