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メソッドはこれを1回だけ実行するため、実際にウィンドウを表示するために必要なメッセージがウィンドウに表示されない場合があります。

于 2013-03-20T23:12:47.533 に答える