Не виден MessageBox

383
27 ноября 2017, 18:57

В общем, дело такое, есть класс окна, который хорошо себя показывает, обработка внутренних сообщений, отрисовки, ресайза, и т.д. и т.п. Загвоздка заключается при попытке отобразить окно сообщения, стандартный MessageBoxW. Окно как бы есть, но его как бы и нет, т.е. если нажать на пробел или на ENTER, то выберется выделенный Button на этом сообщении, при этом его не видно. Есть ли универсальное решение данной проблемы, или в моем случае лучше использовать новый поток для этого сообщения?

Базовый/абстрактный класс окна.

window_base.h

#pragma once
#include <windows.h>
#include <strstream>
namespace base
{
    namespace interop
    {
        class window_base
        {
        public:
            virtual BOOL register_window();
            virtual BOOL register_window(UINT style, HICON h_icon, HCURSOR h_cursor, HBRUSH hbr_background, wchar_t* lpsz_menu_name, wchar_t* lpsz_class_name, HICON h_icon_sm);
            virtual BOOL register_window(const WNDCLASSEXW* wcx);
            static LRESULT CALLBACK st_win_msg_handler(HWND hwnd, UINT u_msg, WPARAM w_param, LPARAM l_param);
            void set_window_title(wchar_t* lpsz_title);
            void set_window_title(std::wstring lpsz_title_str);
            virtual BOOL create();
            virtual BOOL create(DWORD dw_styles, RECT* rect);
            BOOL is_window_closed() const { return b_window_closed_; };
            HWND get_window_handle() const;
            BOOL is_minimized() const;
        protected:
            HINSTANCE h_instance_;
            HWND m_hwnd_;
            BOOL b_window_closed_;
            wchar_t sz_class_name_[256];
            wchar_t sz_window_title_[256];
            explicit window_base(const HINSTANCE h_inst, const WNDCLASSEXW* wcx = nullptr) : h_instance_(nullptr), m_hwnd_(nullptr), b_window_closed_(FALSE)
            {
                h_instance_ = h_inst;
            };
            virtual LRESULT CALLBACK win_msg_handler(HWND hwnd, UINT u_msg, WPARAM w_param, LPARAM l_param) = 0;
            inline static window_base *get_object_from_window(const HWND h_wnd)
            {
                return reinterpret_cast<window_base *>(static_cast<LONG_PTR>(GetWindowLongW(h_wnd, (-21))));
            }
        };
    }
}

window_base.cpp

#include "window_base.h"
namespace base
{
    namespace interop
    {
        BOOL window_base::register_window()
        {
            WNDCLASSEX wcx;
            wcx.cbSize = sizeof(WNDCLASSEX);
            wcx.style = CS_HREDRAW | CS_VREDRAW;
            wcx.lpfnWndProc = st_win_msg_handler;
            wcx.cbClsExtra = 0;
            wcx.cbWndExtra = 0;
            wcx.hInstance = h_instance_;
            wcx.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
            wcx.hCursor = LoadCursor(nullptr, IDC_ARROW);
            wcx.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
            wcx.lpszMenuName = nullptr;
            wcx.lpszClassName = L"BaseWindow";
            wcx.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
            return register_window(&wcx);
        }
        BOOL window_base::register_window(const UINT style, const HICON h_icon, const HCURSOR h_cursor,
                                          const HBRUSH hbr_background,
                                          wchar_t* lpsz_menu_name, wchar_t* lpsz_class_name, const HICON h_icon_sm)
        {
            WNDCLASSEX wcx;
            wcx.cbSize = sizeof(WNDCLASSEX);
            wcx.style = style;
            wcx.lpfnWndProc = st_win_msg_handler;
            wcx.cbClsExtra = 0;
            wcx.cbWndExtra = 0;
            wcx.hInstance = h_instance_;
            wcx.hIcon = h_icon;
            wcx.hCursor = h_cursor;
            wcx.hbrBackground = hbr_background;
            wcx.lpszMenuName = lpsz_menu_name;
            wcx.lpszClassName = lpsz_class_name;
            wcx.hIconSm = h_icon_sm;
            return register_window(&wcx);
        }
        BOOL window_base::register_window(const WNDCLASSEXW* wcx)
        {
            ZeroMemory(sz_class_name_, sizeof(wchar_t) * 256);
            wcscpy_s(sz_class_name_, wcx->lpszClassName);
            if (RegisterClassEx(wcx) == 0)
                return FALSE;
            return TRUE;
        }

        LRESULT CALLBACK window_base::st_win_msg_handler(const HWND hwnd, const UINT u_msg, const WPARAM w_param,
                                                         const LPARAM l_param)
        {
            if (u_msg == WM_NCCREATE)
            {
                SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(LPCREATESTRUCT(l_param)->lpCreateParams));
                return 1;
            }
            window_base* p_wnd = reinterpret_cast<window_base*>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
            if (!p_wnd || !p_wnd->m_hwnd_)
            {
                return DefWindowProc(hwnd, u_msg, w_param, l_param);
            }
            return p_wnd->win_msg_handler(hwnd, u_msg, w_param, l_param);
        }
        void window_base::set_window_title(wchar_t* lpsz_title)
        {
            ZeroMemory(sz_window_title_, sizeof(wchar_t) * 256);
            wcscpy_s(sz_window_title_, lpsz_title);
            SetWindowTextW(m_hwnd_, sz_window_title_);
        }
        void window_base::set_window_title(std::wstring lpsz_title)
        {
            set_window_title(const_cast<wchar_t*>(lpsz_title.c_str()));
        }
        BOOL window_base::create()
        {
            RECT rect;
            rect.top = 0;
            rect.left = 0;
            rect.right = 640;
            rect.bottom = 480;
            return create(WS_OVERLAPPEDWINDOW | WS_VISIBLE, &rect);
        }
        BOOL window_base::create(const DWORD dw_styles, RECT* rect)
        {
            m_hwnd_ = CreateWindowExW(0L, sz_class_name_, sz_window_title_, dw_styles, rect->left, rect->top, rect->right,
                                      rect->bottom, nullptr, nullptr, h_instance_, this);
            return (m_hwnd_ != nullptr);
        }
        HWND window_base::get_window_handle() const
        {
            return m_hwnd_;
        }
        BOOL window_base::is_minimized() const
        {
            return IsIconic(m_hwnd_);
        }
    }
}

Далее идет класс наследник, от которого могут наследоваться перегружая предоставленные методы обработки сообщений.

direct_window_base.h

#pragma once
#include "window_base.h"
#include "data_types.h"
using base::interop::window_base;
namespace base
{
    namespace interop
    {
        class direct_window_base : public window_base
        {
        protected:
            /**
             * \brief Оконная процедура, предоставленная именно для текущего класса окна
             * \param hwnd Handle окна
             * \param u_msg Сообщение
             * \param w_param WORD param
             * \param l_param LONG param
             * \return Ответ обработки сообщения
             */
            LRESULT CALLBACK win_msg_handler(HWND hwnd, UINT u_msg, WPARAM w_param, LPARAM l_param) override;
        public:
            explicit direct_window_base(const HINSTANCE h_inst);
            virtual ~direct_window_base();
            virtual void on_window_close();
            virtual void on_window_destroy();
            virtual void on_mouse_move(POINT pos);
            virtual void on_mouse_down(POINT pos);
            virtual void on_mouse_up(POINT pos);
            virtual void on_key_down(int key_code);
            virtual void on_key_up(int key_code);
            virtual void on_size_changed(RECT rect);
            virtual LRESULT on_system_command(gui::window_data_t data);
            virtual void on_paint(RECT rect, HDC* dc = nullptr, PAINTSTRUCT* ps = nullptr);
        };
    }
}

direct_window_base.cpp

#include "direct_window_base.h"
#include "data_types.h"
#if _DEBUG
#include <iostream>
#endif
namespace base
{
    namespace interop
    {
        LRESULT CALLBACK direct_window_base::win_msg_handler(const HWND hwnd, const UINT u_msg, const WPARAM w_param,
                                                             const LPARAM l_param)
        {
            switch (u_msg)
            {
            case WM_SYSCOMMAND:
                return on_system_command({ hwnd, u_msg, w_param, l_param });
            case WM_CLOSE:
                on_window_close();
                break;
            case WM_MOUSEMOVE:
                on_mouse_move({LOWORD(l_param), HIWORD(l_param)});
                return FALSE;
            case WM_KEYDOWN:
                on_key_down(unsigned long(w_param));
                return TRUE;
            case WM_KEYUP:
                on_key_up(unsigned long(w_param));
                return TRUE;
            case WM_PAINT:
                RECT r;
                GetClientRect(hwnd, &r);
                InvalidateRect(m_hwnd_, &r, false);
                on_paint(r);
                break;
            case WM_SIZE:
                RECT rect;
                GetClientRect(hwnd, &rect);
                on_size_changed(rect);
                return TRUE;
            default:
                return DefWindowProcW(hwnd, u_msg, w_param, l_param);
            }
            return LRESULT(0);
        }
        direct_window_base::direct_window_base(const HINSTANCE h_inst) : window_base(h_inst)
        {
        }
        direct_window_base::~direct_window_base()
        {
        }
        void direct_window_base::on_window_close()
        {
            on_window_destroy();
        }
        void direct_window_base::on_window_destroy()
        {
#if _DEBUG
            wchar_t buffer[255];
            swprintf_s(buffer, L"[module: direct_window_base address: %p] called on_window_close by address: %p", this, &direct_window_base::on_window_close);
            std::wcout << buffer << std::endl;
#endif
            b_window_closed_ = 1;
        }
        void direct_window_base::on_mouse_move(POINT pos)
        {
        }
        void direct_window_base::on_mouse_down(POINT pos)
        {
        }
        void direct_window_base::on_mouse_up(POINT pos)
        {
        }
        void direct_window_base::on_key_down(int key_code)
        {
        }
        void direct_window_base::on_key_up(int key_code)
        {
        }
        void direct_window_base::on_size_changed(RECT rect)
        {
        }
        LRESULT direct_window_base::on_system_command(const gui::window_data_t data)
        {
            return DefWindowProcW(data.hwnd, data.msg, data.wparam, data.lparam);
        }
        void direct_window_base::on_paint(RECT rect, HDC* dc, PAINTSTRUCT* ps)
        {
        }
    }
}

window.h

#pragma once
#include "direct_window_base.h"
namespace base
{
    enum message_box_type
    {
        error,
        information,
        warning,
        question
    };
    enum message_box_buttons
    {
        ok,
        yes_no,
        yes_no_cancel,
        retry_cancel
    };
    namespace controls
    {
        class window : public interop::direct_window_base
        {
        public:
            explicit window(HINSTANCE h_instance, std::wstring window_title);
            ~window() override;
            bool show() const;
            void set_window_icon(HICON icon) const;
            void set_window_icon_small(HICON icon) const;
            RECT get_window_rect() const;
            void loop();
            int message_box(std::wstring message, std::wstring title, message_box_buttons mbbox_btn, message_box_type mbbox_type);
            void on_mouse_move(POINT pos) override;
            void on_mouse_down(POINT pos) override;
            void on_mouse_up(POINT pos) override;
            void on_key_down(int key_code) override;
            void on_key_up(int key_code) override;
            void on_size_changed(RECT rect) override;
            void on_paint(RECT rect, HDC* dc, PAINTSTRUCT* ps) override;
            LRESULT on_system_command(gui::window_data_t data) override;
        };
    }
}

window.cpp

#include "window.h"
#include <iostream>
#include "resource.h"
#include "engine.h"
namespace base
{
    namespace controls
    {
        window::window(const HINSTANCE h_instance, const wstring window_title) : direct_window_base(h_instance)
        {
            if (!window_base::register_window(CS_HREDRAW | CS_VREDRAW, LoadIconW(h_instance, MAKEINTRESOURCEW(IDI_ICON1)),
                                              LoadCursorW(nullptr, IDC_ARROW), HBRUSH(GetStockObject(NULL_BRUSH)), nullptr,
                                              L"awgui_window_class", LoadIconW(nullptr, MAKEINTRESOURCEW(IDI_ICON1))))
            {
                throw exception("Unable to register window class\n");
            }
            RECT rect = {0,0,800,600};
            AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
            int x = GetSystemMetrics(SM_CXSCREEN) / 2 - (rect.right - rect.left) / 2;
            int y = GetSystemMetrics(SM_CYSCREEN) / 2 - (rect.bottom - rect.top) / 2;
            int err = memcpy_s(&rect.left, sizeof x, &x, sizeof rect.left);
            if (err == -1)
            {
                wcout << L"memcpy_s(&rect.left, sizeof x, &x, sizeof rect.left) failed" << endl;
            }
            err = memcpy_s(&rect.top, sizeof y, &y, sizeof rect.top);
            if (err == -1)
            {
                wcout << L"memcpy_s(&rect.top, sizeof y, &y, sizeof rect.top) failed" << endl;
            }
            if (!window_base::create(WS_OVERLAPPEDWINDOW, &rect))
            {
                UnregisterClassW(sz_class_name_, h_instance_);
                throw exception("Unable to create window\n");
            }
            const HMENU menu = GetSystemMenu(m_hwnd_, FALSE);
            AppendMenuW(menu, MF_STRING, 101, L"Visit website");
            set_window_title(window_title);
        }
        window::~window()
        {
            window* self = this;
            engine::get_engine(&self)->release();
            DestroyWindow(m_hwnd_);
            UnregisterClassW(sz_class_name_, h_instance_);
        }
        bool window::show() const
        {
            return ShowWindow(m_hwnd_, SW_SHOW);
        }
        void window::set_window_icon(HICON icon) const
        {
            SendMessageW(m_hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(icon));
            SendMessageW(m_hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icon));
        }
        void window::set_window_icon_small(HICON icon) const
        {
            SendMessageW(m_hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icon));
        }
        RECT window::get_window_rect() const
        {
            RECT r;
            GetClientRect(m_hwnd_, &r);
            return r;
        }
        void window::loop()
        {
            MSG msg = {nullptr};
            window* self = this;
            while (msg.message != WM_QUIT && !is_window_closed())
            {
                if (PeekMessageW(&msg, m_hwnd_, 0, 0, PM_REMOVE))
                {
                    TranslateMessage(&msg);
                    DispatchMessageW(&msg);
                }
                engine::get_engine(&self)->run();
                if (this->is_minimized())
                {
                    Sleep(1);
                }
            }
        }
        int window::message_box(wstring message, wstring title,
                                const message_box_buttons mbbox_btn, const message_box_type mbbox_type)
        {
            long mb_data = 0L;
            switch (mbbox_btn)
            {
            case ok:
                mb_data |= MB_OK;
                break;
            case yes_no:
                mb_data |= MB_YESNO;
                break;
            case yes_no_cancel:
                mb_data |= MB_YESNOCANCEL;
                break;
            default: mb_data |= 0L;
            }
            switch (mbbox_type)
            {
            case error:
                mb_data |= MB_ICONERROR;
                break;
            case information:
                mb_data |= MB_ICONINFORMATION;
                break;
            case warning:
                mb_data |= MB_ICONWARNING;
                break;
            case question:
                mb_data |= MB_ICONQUESTION;
                break;
            default: mb_data |= 0;
            }
            return MessageBoxW(m_hwnd_, message.c_str(), title.c_str(), mb_data);
        }
        void window::on_mouse_move(const POINT position)
        {
            wchar_t buffer[255];
            wsprintfW(buffer, L"[module: window address: %p] Mouse position: is x=%d y=%d", const_cast<window*>(this), position.x, position.y);
            wcout << buffer << endl;
        }
        void window::on_mouse_down(POINT pos)
        {
        }
        void window::on_mouse_up(POINT pos)
        {
        }
        void window::on_key_down(const int key_code)
        {
#if _DEBUG
            wchar_t buffer[255];
            wsprintfW(buffer, L"[module: window address: %p] Key code is down: %d", const_cast<window*>(this), key_code);
            wcout << buffer << endl;
#endif
        }
        void window::on_key_up(const int key_code)
        {
#if _DEBUG
            wchar_t buffer[255];
            wsprintfW(buffer, L"[module: window address: %p] Key code is up: %d", const_cast<window*>(this), key_code);
            wcout << buffer << endl;
#endif
        }
        void window::on_size_changed(const RECT rect)
        {
#if _DEBUG
            wchar_t buffer[255];
            wsprintfW(buffer, L"[module: window address: %p] Size is %d %d", const_cast<window*>(this), rect.right - rect.left,
                      rect.bottom - rect.top);
            wcout << buffer << endl;
#endif
            window* self = this;
            engine::get_engine(&self)->resize(rect);
        }
        void window::on_paint(RECT rect, HDC* dc, PAINTSTRUCT* ps)
        {
            window* self = this;
            engine::get_engine(&self)->run();
        }
        LRESULT window::on_system_command(const gui::window_data_t data)
        {
            switch (data.wparam)
            {
            default:
                return direct_window_base::on_system_command(data);
            }
            //return LRESULT(0);
        }
    }
}
READ ALSO
Вывод объема оперативной памяти

Вывод объема оперативной памяти

Здравствуйте! Есть задание вывести общий объём физической памяти и свободный объём физической памяти в МбИспользую структуру MEMORYSTATUS из библиотеки...

340
синглтон майерса и многопоточность

синглтон майерса и многопоточность

здравствуйте, не раз слышал фразу, что "после c++11 синглтон майерса стал потокобезопасным"

302
Не удаётся открыть файл с помощью std::ifstream

Не удаётся открыть файл с помощью std::ifstream

Привет, не найду костыльХочу свою функцию для чтения/записи файлов, но оно не хочет считывать

354