1

Win32固有のGUIコンポーネントの周りに優れたラッパーを作成しようとしたときに、最終的に問題が発生しました。問題は、作成したウィンドウが存在しなくなった後、アプリケーションを閉じることができないことです。

私のAPIは次のように機能します。

/// ----------------------------
/// @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;
}

このように宣言された「アクティブ」と呼ばれるHelixirrWidgets::Windowのメソッドで

inline bool active(void) const noexcept;

ウィンドウがアクティブかどうかを確認できます。

このメソッドは基本的に、インスタンスのブールメンバー変数へのconst参照を返します。このメンバー変数は、同じクラスの「show」メソッドで変更されます。定義は次のとおりです。

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;
}

プラットフォーム固有の構造を非表示にするためにpimpl-idiomを使用していることに注意してください(「_m_opHelper」は実装へのポインターです)。

動作しているように見えるかもしれませんが、動作せず、理由がわかりません。それはすべて簡単な質問に帰着します:WINAPI固有の関数と構造を使用して実装されたウィンドウを閉じて、アプリケーションのユーザーが適切に閉じるにはどうすればよいですか?

4

1 に答える 1

1

WM_CLOSE問題の原因は、単に最後のメッセージが表示されないという事実に関連していると思いますHWND。のようなメッセージWM_DESTROYWM_NCDESTROYおよび場合によってはそれ以上のメッセージ(特定のウィンドウとその状態によって異なります)がの後に続きWM_CLOSE、割り当てにつながり_m_bActive = TRUEます。

つまり、ウィンドウは非常に短時間非アクティブになり、(おそらく)同時に非アクティブになることはなく、で無限ループが発生しmain()ます。

于 2013-03-18T13:42:54.630 に答える