【问题标题】:C++ - WINAPI - Object-oriented approach to closing a windowC++ - WINAPI - 面向对象的关闭窗口的方法
【发布时间】:2013-03-18 13:14:29
【问题描述】:

在尝试围绕 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方法中调用“active”,声明如下

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 特定函数和结构实现的窗口,以由我的应用程序用户适当关闭

【问题讨论】:

  • 具有双下划线或下划线后跟大写字母的标识符由实现(即编译器和库)保留。不要使用它们。您的编译器可能会召唤鼻恶魔。即使是上帝也无法抵挡他们的邪恶力量。
  • 人们会认为上帝关闭应用程序没有任何困难。
  • 感谢您的建议,但我想以这种方式将局部变量与代码中存在的所有其他变量区分开来。我知道如果你不知道你正在使用预处理器定义或其他东西,下划线可能会产生意想不到的结果,但到目前为止,我从未遇到过这种方法的问题。
  • @Floris Velleman:上帝帮助我编码,你知道的。如果你明白我的意思,对他所做的所有好事负责是错误的。 :-)
  • 您这样做从根本上是错误的,消息循环是线程属性,而不是窗口属性。如果你想重新发明这个轮子,那么至少看看许多其他 GUI 类库的做法。

标签: c++ winapi window


【解决方案1】:

我想问题的原因与WM_CLOSE 根本不是HWND 收到的最后一条消息有关。 WM_DESTROYWM_NCDESTROY 之类的消息以及可能更多(取决于特定窗口及其状态)将出现在 WM_CLOSE 之后,从而导致分配 _m_bActive = TRUE

即窗口在很短的时间内变为非活动状态,并且(很可能)它们永远不会同时处于非活动状态,从而导致main() 中的无限循环。

【讨论】:

  • 您的建议帮助我找到了解决方案:PostQuitMessage(0) 位置错误。
猜你喜欢
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
  • 2015-12-27
  • 1970-01-01
  • 2018-09-02
相关资源
最近更新 更多