【问题标题】:How to organize correctly Win32 message handling with DirectX?如何使用 DirectX 正确组织 Win32 消息处理?
【发布时间】:2013-03-06 18:48:30
【问题描述】:

我目前正在尝试开发一个基于 DirectX 和 Win32 API 的小型渲染引擎。我目前正在尝试解决的问题是如何正确组织我的代码以处理影响 DirectX 代码的 Windows 消息(例如,WM_SIZE 消息,这意味着调整 DirectX 缓冲区的大小)。

需要在创建时传递给窗口的WndProc函数中完成,但我不知道如何“传递”我感兴趣的消息。到目前为止,我只找到了这样:

//main.cpp
Renderer* renderer;

//some code 

//The window procedure
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    PAINTSTRUCT ps;
    HDC hdc;

    //We forward the message to the Renderer, which handles it or not
    if(renderer->HandleMessage(hWnd,message,wParam,lParam){
        return 0;
    }

    //If the renderer does not handle the message, we do as usual
    switch( message )
    {
        case WM_PAINT:
            hdc = BeginPaint( hWnd, &ps );
            EndPaint( hWnd, &ps );
            break;

        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;

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

    return 0;
}

我对这种方法的问题是它依赖于一个全局变量(渲染器),我对此感到不舒服,因为我听说很多使用全局变量不是好的做法(而且我觉得我'我没有足够的经验来决定是否应该使用它)

我想知道是否有更好的方法来“转发”窗口消息而不需要全局变量。

【问题讨论】:

    标签: c++ winapi directx


    【解决方案1】:

    首先,WM_PAINT 用于 GDI 绘画,而不是 Direct3D 渲染。通常,D3D 应用会尽可能渲染帧。

    其次,使用SetWindowLongPtr 将指向渲染器的指针设置为与HWND 关联的内部Windows 变量,您可以使用GetWindowLongPtr 获取该变量。

    第三,你真的应该有一个 Window 类来包装它,然后它会选择告诉渲染器,而不是直接交互。

    编辑:这是正常的超简单结构:

    class Window {
        HWND hwnd;
        static ... WindowProc(...) {
            if (auto p = GetWindowLongPtr(hwnd, GWLP_USERDATA))
                return reinterpret_cast<Window*>(p)->ProcessMessage(...);
            else return DefWindowProc(...);
        }
        ... ProcessMessage(...) {
            /* whatever you want */
            if (msg == WM_RESIZE)
                OnResize(...);
        }
    public:
        Window() {
            hwnd = CreateWindowEx(...);
            SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
        }
        std::function<void(unsigned, unsigned)> OnResize;
    };
    

    在这种情况下,ProcessMessage() 是一个成员,Window 只提供一个回调,允许任何外部代码挂钩到这个特定事件。

    【讨论】:

    • 感谢您的评论。我查看了SetWindowLongPtrGetWindowLongPtr。如果我做对了,我应该使用SetWindowLongPtrGWLP_USERDATA属性中存储指向我的渲染器的指针,然后使用getter,将返回的值转换为指向渲染器的指针,并调用适当的成员函数( s) ?无论如何,我真的不明白如何将其包装在 Window 类中,因为我仍然需要在 WNDCLASSEX 结构中为lpfnWndProc 提供一个非成员函数...
    • @JBL:是的,没错。您提供一个非成员作为 WNDPROC,但使用 GWLP_USERDATA 指针槽来存储一个类指针,您可以立即在其上调用一个成员函数。
    猜你喜欢
    • 2016-02-10
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 2010-12-14
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 2014-10-27
    相关资源
    最近更新 更多