【问题标题】:Self-destructing class containing a window包含窗口的自毁类
【发布时间】:2011-10-02 15:44:31
【问题描述】:

我创建了一个打印预览类 PPREVIEW,其中包含一个打印预览窗口,它应该在我的应用程序的主窗口上弹出,同时禁用它。当用户关闭预览窗口时,应该启用主窗口并销毁 PPREVIEW 对象。我想通过以下方式使用它:

PPREVIEW *p=new PPREVIEW;
//next, preview window is created, user interaction begins
p->ShowPreview(<parameters>); //but this function returns
delete p;

由于 ShowPreview 确实返回,上面的行将在窗口仍然可见时破坏对象。如果它是一个模态对话框,这是可能的,因为 DialogBox 函数此时不会返回。 我想我可以在打印预览窗口被破坏时将“删除”放在某处。自然会想到 WM_DESTROY。但是 MSDN 在http://msdn.microsoft.com/en-us/library/windows/desktop/ms632620%28v=vs.85%29.aspx 声明以下内容:“可以假设在处理 WM_DESTROY 期间子窗口仍然存在”,因此它们中的一些仍然有可能引用实例的变量(并且确实如此,我遇到了随机访问冲突错误当我尝试这样做时,我退出了)。

目前我选择:
- 创建一些全局变量,
- 在打印预览窗口的 WM_DESTROY 中,我输入 EnableWindow(MainWindow, TRUE) 并将该全局变量设置为 FALSE。
- 然后,在主窗口的 WM_ENABLE 事件中,我正在测试全局变量是否为 FALSE 并删除对象。

但这很不优雅,需要我为每个使用打印预览的窗口编写此行为,所以我决定采用以前的方法,即:创建、使用,可能是自删除。我需要:
- 我什么时候可以在 PPREVIEW 窗口过程中使用“删除这个”的信息,如果由于某种原因这种方法不是不明智的,我不知道
- 如何使 ShowPreview 方法不返回,模仿 DialogBox 行为的想法。
- 实现我目标的其他建议

请帮忙。

【问题讨论】:

  • 如果窗口是模态的,为什么 ShowPreview 返回?另外,这里不要使用new,根本不需要。
  • 我应该澄清一下:窗口不是模态的,它是由 CreateWindowEx 创建的,我只提到了 DialogBox 函数,因为我希望我的窗口也能这样。
  • @Kitet: DialogBox 不会仅仅因为它是模态的而返回。

标签: c++ winapi


【解决方案1】:
  1. 您的ShowPreview 函数应调用ShowWindow() 以显示预览窗口。它还应该对主表单执行任何操作,例如禁用它。
  2. 当您的预览窗口收到WM_CLOSE 时,它应该删除包装它的C++ 对象。此过程的某些部分还需要在底层窗口句柄上调用DestroyWindow()WM_CLOSE 的默认处理方式会执行此操作,但您可能希望在 C++ 对象的析构函数中执行此操作。

【讨论】:

  • 实际上,我想要自毁类或模态窗口。由于我更接近您的答案,因此我尝试了替代消息循环,并且它有效。在接受答案之前,将测试几天。上次我把“删除这个”放在 WM_DESTROY 中,它导致了随机问题。现在,我想我已经准备好了。
【解决方案2】:

如果您希望ShowPreview 成为模态,则需要运行子消息循环。您可以找到 some examples here,包括 DialogBox 在内部使用的逆向工程版本。

或者,您可以简单地让预览窗口的WM_DESTROY 重新启用主窗口并删除您的PPREVIEW *(在这种情况下ShowPreview 将不是模态的,但它将是独立的)。在DestroyWindow() 调用之后,您必须小心不要触摸PPREVIEW *(或者,在PPREVIEW 的成员函数中,不要调用任何其他成员或访问任何成员变量) - 这特别意味着DefWindowProc() 调用后,您无法访问消息处理程序中的成员变量

【讨论】:

  • 现在将尝试子消息循环。 WM_DESTROY 的事情 - 我一开始就这样做了,并且在关闭预览窗口很久之后就发生了许多访问冲突,正如我上面所写的。我花了几个小时才把它们追溯到这个。
  • @Kitet 子消息循环是您为模态窗口所做的。但是你说你想要一个应该从主消息循环运行的无模式窗口。你想要一个模态窗口吗?我现在不确定。
  • @DavidHeffernan:bdonlan 显示的循环虽然在某种意义上是模态的,但不会导致子窗口或父窗口的模态行为。对话框的模态消息循环处理其包含树之外的窗口的消息,而不调用窗口过程。
  • @BenVoigt,如何在不调用窗口过程的情况下处理消息?
  • @bdonlan:不管怎样,我记得对话框模式循环有一些特别之处......它是对IsDialogMessage 的调用,而你的循环丢失了。
猜你喜欢
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 2012-05-16
  • 2020-02-22
  • 1970-01-01
  • 1970-01-01
  • 2017-04-30
  • 1970-01-01
相关资源
最近更新 更多