在类中封装Win32 - 在CreateWindow中传递类指针

时间:2015-12-28 20:09:17

标签: windows winapi

我在这个主题上看了很多教程和帖子,他们都说我在我的this函数中传递了类实例指针(CreateWindowEx()),然后将它存储在窗口过程函数中,发送WM_NCCREATE消息。我想这是因为WM_NCCREATE被认为是自创建窗口以来第一个被发送到窗口过程的消息。

一些问题/说明:

  1. 从调试开始,我发现实际上WM_GETMINMAXINFO是第一个发送的消息,之前 WM_NCCREATE(至少在我的机器上)。这是否意味着我应该听取此消息而不是WM_NCCREATE

  2. 根据RemoveAll()热门文章,收到消息SetWindowLongPtr()后每个人调用WM_NCCREATE的原因是因为

      

    如果在WM_NCCREATE被调用时该值不存在,那么,   通过一些神秘的Windows行为,我仍然不明白,   价值永远不会被插入。

  3. 我试图这样做(即在SetWindowLongPtr()之后调用CreateWindowEx())。事实证明这很好。该应用程序运行正常。以下是我的代码,请告诉我这种方法是否有问题。

    void GLWin32::CreateWindow(...)
    {
        ...
    
        _hwnd = CreateWindowEx(NULL, _wndclassex.lpszClassName, title.c_str(), WS_OVERLAPPEDWINDOW, x, y, width, height, NULL, NULL, _hinstance, NULL);
        SetWindowLongPtr(_hwnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(this));
    
        ...
    }
    
    //static window procedure for all instances of this class
    LRESULT CALLBACK GLWin32::_msgRouter(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
        LONG l = GetWindowLongPtr(hwnd, GWLP_USERDATA);
        GLWin32* thisPtr = reinterpret_cast<GLWin32*>(l);
    
        if (thisPtr)
            return thisPtr->_winProc(msg, wparam, lparam);
        else
            return DefWindowProc(hwnd, msg, wparam, lparam);
    }
    
    LRESULT GLWin32::_winProc(UINT msg, WPARAM wparam, LPARAM lparam)
    {
        switch (msg)
        {
        case WM_CLOSE:
        {
            PostQuitMessage(0);
            return 0;
        }
        }
    
        return DefWindowProc(_hwnd, msg, wparam, lparam);
    }
    

    为什么不使用我的方法而不是this

1 个答案:

答案 0 :(得分:2)

这种方法的问题在于,如果您想在处理任何窗口创建消息(包括作为创建过程的一部分发送的“普通”消息)时使用该实例,您将无法访问它

假设您要在处理 WM_CREATE (典型方案)时创建按钮,并且您希望将按钮文本设置为某个实例成员值。你想要这样的东西:

LRESULT GLWin32::_winProc(UINT msg, WPARAM wparam, LPARAM lparam)
{
    switch (msg)
    {
    case WM_CREATE:
    {
        CreateWindow("BUTTON", this->buttonText, WS_VISIBLE | WS_CHILD,
          10, 10, 50, 30, this->hwnd, NULL, this->hInstance, NULL);
        return 0;
    }
    }

    return DefWindowProc(_hwnd, msg, wparam, lparam);
}

问题是,当处理 WM_CREATE 时(在CreateWindowEx返回之前),SetWindowLongPtr尚未被调用且实例指针丢失,因此_winProc根本没有被召唤。