Helixirr
Helixirr

Reputation: 931

C++ - WINAPI - Object-oriented approach to closing a window

While trying to create a nice wrapper around Win32 specific GUI components, I eventually ran into a problem. The problem is that I'm unable to close the application after the windows I created no longer exist.

My API works like this:

/// ----------------------------
/// @author     God
/// @project    Helixirr Widgets
/// ----------------------------
#include <helixirrwidgets/HelixirrWidgets.hpp>

int main(void){
    HelixirrWidgets::Window __windows[2] = {HelixirrWidgets::Window("Big Window"), HelixirrWidgets::Window()};

    __windows[0].position(200, 200);
    __windows[0].size(800, 600);
    __windows[0].visible(true);
    __windows[0].save_changes();

    __windows[1].name("Tiny Window");
    __windows[1].position(10, 100);
    __windows[1].size(400, 200);
    __windows[1].visible(true);
    __windows[1].save_changes();

    while(__windows[0].active() || __windows[1].active()){
        if(__windows[0].visible()){
            __windows[0].show();
        }
        if(__windows[1].visible()){
            __windows[1].show();
        }
    }
    return 0;
}

In method of HelixirrWidgets::Window called "active", which is declared like this

inline bool active(void) const noexcept;

I can check, whether my window is active or not.

This method basically return a const reference to a boolean member variable of an instance. This member variable is modified in "show"-method of the same class. Here's the definition:

void Window::show(void){
    if(GetMessage(&_m_opHelper->message, _m_opHelper->handle_window, 0, 0)){
        if(_m_opHelper->message.message == WM_CLOSE){
            _m_bActive = false;
            return;
        }

        TranslateMessage(&_m_opHelper->message);
        DispatchMessage(&_m_opHelper->message);

        ShowWindow(_m_opHelper->handle_window, SW_SHOWDEFAULT);
        UpdateWindow(_m_opHelper->handle_window);

        _m_bActive = true;
        return;
    }
    _m_bActive = false;
}

Do note I use pimpl-idiom to hide platform-specific structures ("_m_opHelper" is pointer to implementation).

It may look like it works, but it doesn't and I can't understand why. It all comes down to a simple question: how can I close my window implemented using WINAPI specific functions and structures to be closed appropriately by a user of my application?

Upvotes: 1

Views: 212

Answers (1)

mity
mity

Reputation: 2349

I guess the cause of the issue is related to the fact WM_CLOSE simply is not last message HWND gets. Messages like WM_DESTROY, WM_NCDESTROY and possibly more (depending on the particlar window and its state) will come after WM_CLOSE, leading to the assignment _m_bActive = TRUE.

I.e. the window becomes inactive for very short time, and (likely) they will never be inactive at the same time, causing an endless loop in main().

Upvotes: 1

Related Questions