使用元编程处理窗口消息

时间:2012-04-07 17:42:38

标签: c++ winapi metaprogramming wrapper template-meta-programming

我正在学习如何包装一些基本的WinAPI功能(如窗口创建)。我为窗口类编写了一个包装类,为基本窗口编写了一个包装类。

在我的窗口过程的实现中,我一直密切关注此链接中描述的消息路由器:Creating a Win32 Window Wrapper

将基本窗口类的this指针传递给CreateWindowEx函数并使用SetWindowLongPtr将其附加到窗口的想法。消息路由器作为窗口过程传递给我创建的每个窗口类,它调用每个窗口作为私有函数的窗口过程。 (消息路由器是我的基本窗口类的朋友)

我现在的主要问题是如何处理我的窗口获取的消息。我不喜欢作者在上面的链接中使用的解决方案,因为如果我必须为我想要处理的每个窗口消息注册一个回调函数,我发现它很烦人。我还想在separete控制器类中处理这些消息,而不是窗口类本身。

在我的脑海中,最佳解决方案是:

BasicWindow window("Window Class", program_instance);
window.create()

Controller controller;
window.setController(controller);

从那时起我会喜欢这个窗口自己弄清楚控制器提供回调的消息。

我已经有了一些想法:

  1. 为控制器提供一个抽象基类,该控制器具有各种回调函数的原型。但是这样我就不得不在每个控制器中处理它们,即使我不需要它们(例如,我不需要在普通的编辑控件中处理WM_PAINT。)所以这太严格了。

  2. 让每个控制器都有一个函数,它返回一个无符号整数的数组/向量,告诉窗口控制器处理哪些消息。这很烦人,因为每次我向控制器添加另一条消息的新回调函数时,我都不能忘记更新向量。这种方法的另一个缺点是我要么必须在BasicWindow类中保存这个向量,要么每次调用windows窗口过程时都要从控制器请求它,我必须搜索向量是否包含消息收到的窗口。

  3. 我最近的想法是某种预处理。由于我不打算在运行时更改窗口的控制器,我认为这可能是预处理甚至元编程可能有用的情况。我只阅读了一些关于元编程的文章,并没有太多关于它的线索,但我认为它可能是一个合适的解决方案。我想到的是以下内容:

    • 在我的控制器中,我想为我的回调函数添加某种限定符。类似于void paint() <WM_PAINT>;
    • 的东西
    • 然后我希望编译器在Windows窗口过程中生成一个if语句,该过程在收到WM_PAINT消息时调用paint函数。这将节省我对矢量/数组的运行时检查,并使其非常轻松,并且仍然可以灵活地编写我的控制器。
  4. 就我个人而言,我会喜欢我在3中所描述的方式。不幸的是,正如我前面提到的,我的元编程技巧几乎不存在。我希望你们中的一些人能够把我推向正确的方向。

    [编辑] 经过一夜好眠,我或许可以更好地解释我想要的东西。

    我有一个在编译时完全知道的Controller类。它应该看起来像这样:

    class Controller {
    public:
        Controller(DeviceContext& device_context);
        ~Controller();
    
        // If WM_PAINT is received by the window it is supposed to call
        void paint();
        // WM_RESIZE
        void resize(LPARAM lParam);
        ...
    private:
        // class members needed during the performance of the callback functions
        ...
    };
    

    在我的BasicWindow类中,我有一个窗口过程,如上所述由消息路由器调用。看起来有点像:

    LRESULT CALLBACK BasicWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
        // Here I want the magic to happen. I want the compiler to somehow figure out
        // which messages are handled by the controller and generate code like
        if (message == WM_PAINT)
            controller->paint();
    
        return 0;
    }
    

    我的主要问题是我不知道是否和/或如何做到这一点。也许我可以进一步澄清我的问题。

0 个答案:

没有答案