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()ので、イベント定義を常に追加/削除することにユーザーが重くならず、簡単な代替手段を探しています。

4

1 に答える 1

1

標準のプリプロセッサを使用して正確にやりたいことを行うことはできませんが、Bo Persson のコメントに従って、次のようなことができます。

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);
}

少しエラー チェックが必要です。メッセージ ハンドラが定義されていない場合、Dispatch 呼び出しは失敗します。また、おそらくテンプレート クラスを #define に移動することもできますが、そうすると #define が大きくなります。

于 2012-06-22T09:04:44.880 に答える