0

在尝试找到处理窗口消息的合适解决方案时,我在 StackOverflow 上遇到了这个问题:

面向对象的c++ win32?

答案提供了很好的解决方案,我个人最喜欢的是使用 std::map 的公认答案。

但是,每当我在我的代码中使用 std::map 时,它看起来像这样:

#include <cstdio>
#include <map>
#include <windows.h>
#include <helixirrwidgets/Window.hpp>
using namespace HelixirrWidgets;

/// ----------------------------
/// @class  Window
/// @brief  Represents a window.
/// ----------------------------
/// Inner classes:
class Window::Helper{
public:

    /// Constructors & destructors:
    Helper(void) : active(false), created_window(false), handle_instance(GetModuleHandle(NULL)), handle_window(nullptr), message({0}){
        _ms_mopopHelpers.insert({handle_window, this});
    }
    Helper(Helper const& helper_) : active(false), created_window(false), handle_instance(helper_.handle_instance), handle_window(helper_.handle_window), message(helper_.message){
        _ms_mopopHelpers.insert({handle_window, this});
    }
    Helper(Helper&& helper_) : active(false), created_window(false), handle_instance(std::move(helper_.handle_instance)), handle_window(std::move(helper_.handle_window)), message(std::move(helper_.message)){
        helper_.handle_instance = nullptr;
        helper_.handle_window = nullptr;
        _ms_mopopHelpers.insert({handle_window, this});
    }
    ~Helper(void){
        handle_instance = nullptr;
        handle_window = nullptr;
        _ms_mopopHelpers.erase(handle_window);
    }

    /// Member data:
    bool mutable active, created_window;
    HINSTANCE mutable handle_instance;
    HWND mutable handle_window;
    MSG message;

    /// Member functions (overloaded operators, assignment):
    Helper& operator=(Helper const& helper_) = default;
    Helper& operator=(Helper&& helper_) = default;

    /// Static member functions:
    static LRESULT CALLBACK handle_callback(HWND handle_window_, UINT message_, WPARAM wparam_, LPARAM lparam_){
        if(_ms_mopopHelpers.size() != 0){
            // Delegate message handling:
            return _ms_mopopHelpers[handle_window_]->_handle_callback(message_, wparam_, lparam_);
        }
        return 0;
    }

private:
    /// Member functions:
    LRESULT _handle_callback(UINT message_, WPARAM wparam_, LPARAM lparam_){
        switch(message_){
            case WM_DESTROY:
                active = false;
                DestroyWindow(handle_window);
                return 0;
            default:
                return DefWindowProc(handle_window, message_, wparam_, lparam_);
        }
    }
    /// Static member data:
    static std::map<HWND, Window::Helper*> _ms_mopopHelpers;
};
    /// Static member data:
    std::map<HWND, Window::Helper*> Window::Helper::_ms_mopopHelpers = {};
/// Constructors & destructors:
Window::Window(void) : _m_bVisible(false), _m_opHelper(new Window::Helper){

}
Window::Window(Window const& window_) = default;
Window::Window(Window&& window_) = default;
Window::Window(std::string const& name_) : _m_bVisible(false), _m_opHelper(new Window::Helper), _m_oName(name_){

}
Window::Window(std::string&& name_) : _m_bVisible(false), _m_opHelper(new Window::Helper), _m_oName(std::move(name_)){

}
Window::~Window(void) = default;
/// Member functions:
bool const& Window::active(void) const noexcept{
    return _m_opHelper->active;
}
Window& Window::save_changes(void){
    // Create and register window class:
    static bool __registered_class_window = false;
    static WNDCLASSEX __class_window = {
        sizeof(WNDCLASSEX),
        CS_HREDRAW | CS_VREDRAW,
        Window::Helper::handle_callback,
        0, 0,
        _m_opHelper->handle_instance,
        LoadIcon(_m_opHelper->handle_instance, NULL),
        LoadCursor(NULL, IDC_ARROW),
        reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)),
        NULL,
        "Helixirr Widgets Window Class Basic",
        LoadIcon(_m_opHelper->handle_instance, NULL)
    };
    if(!__registered_class_window){
        RegisterClassEx(&__class_window);
        __registered_class_window = true;
    }

    // If window hasn't been created yet:
    if(!_m_opHelper->created_window){
        _m_opHelper->created_window = true;
        _m_opHelper->handle_window = CreateWindowEx(
            0,
            "Helixirr Widgets Window Class Basic",
            _m_oName.c_str(),
            WS_OVERLAPPEDWINDOW,
            _m_uiPos[0], _m_uiPos[1],
            _m_uiSize[0], _m_uiSize[1],
            NULL, NULL, _m_opHelper->handle_instance, NULL
        );
    }
    _m_opHelper->active = true;
    return *this;
}
void Window::show(void){
    if(_m_opHelper->active){
        if(GetMessage(&_m_opHelper->message, NULL, 0, 0)){
            // Handle messages:
            TranslateMessage(&_m_opHelper->message);
            DispatchMessage(&_m_opHelper->message);

            // Handle window displaying:
            ShowWindow(_m_opHelper->handle_window, SW_SHOWDEFAULT);
            UpdateWindow(_m_opHelper->handle_window);
            return;
        }
    }
}

我的窗户由于某种原因没有打开。在切断与 std::map 的所有连接后,窗口再次显示得很好。是什么导致了这种奇怪的现象?很难相信会有某种冲突。

4

1 回答 1

0

从您的 Window::show 方法来看,问题可能是您没有消息循环。正常的消息循环如下所示:

MSG msg = {};

while (GetMessage(&msg, nullptr, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

但是您的 Window::show 方法只执行一次,因此窗口可能不会获得实际显示窗口所需的消息。

于 2013-03-20T23:12:47.533 回答