取消模态化对话框(使模态对话框非模态)

Soc*_*owi 7 windows dialog window desktop-customization windows-10

我使用的是 Windows 10,并且对内置应用程序(例如 Windows-Explorer 的选项对话框)和第三方应用程序(例如Eclipse 的运行配置对话框)的许多模式对话框感到恼火。

例子

打开 Windows 资源管理器 ( Win+ E),转到选项卡View,然后单击Options。选项对话框打开。只要选项对话框保持打开状态,您就无法与资源管理器窗口(您从中打开对话框)进行交互。甚至禁止移动或调整窗口大小。

我没有看到这种行为的原因。打开选项对话框后,我仍然可以打开另一个资源管理器窗口(在同一进程中运行)并与该窗口交互。我认为,资源管理器完全能够允许与打开选项对话框的窗口进行交互。

提到的第三方应用程序也是如此。

? 是否有工具*可以使模态窗口成为非模态窗口?
* 您可以将“工具”一词替换为hack、补丁或您想到的任何内容。

理想情况下,该工具将适用于系统上的所有窗口。但是,也欢迎以下部分解决方案:

  • 在一个特定的 UI 库(例如 Windows 窗体或 Java Swing)中禁用模式的工具
  • 在一个特定应用程序(例如 Windows 资源管理器)中禁用模式的工具
  • 允许移动和调整背景窗口(从中打开模态对话框)的工具,但不能以任何其他方式与之交互。这是一些 Linux 窗口管理器的默认设置,例如 Cinnamon。

当其他被禁止的交互以不可预见的方式改变应用程序的状态时,受影响的应用程序崩溃是可以的(例如,在模式对话框中编辑其属性时删除后台窗口中的项目)。

.


?? 以下部分对我的问题并不重要,但可能对您的回答很重要。如果您要写诸如“那不可能”之类的话,如果您能先阅读它们并仔细考虑一下,我会很高兴。

但是,我必须请求您:请不要开始讨论实施细节。我对自己实现这个不太感兴趣。这就是为什么我在 superuser.com 而不是在 stackoverflow.com 上询问的原因。


解决方案的类似问题

我肯定您可以拦截创建模态对话框的调用;毕竟类似的问题也有解决方案:

  • 任何不可调整大小的对话框都可以使用ResizeEnable调整大小。
    有趣(或悲伤?)事实:ResizeEnable 上次更新是在 2003 年,但仍然适用于 Windows 10,没有任何问题。(Windows XP 于 2001 年发布,但从 ResizeEnable 的更改日志看来,作者在上次发布时并未使用 XP。)

  • 许多全屏应用程序可以使用DxWnd在窗口中运行

技术细节

我非常清楚模态对话框可以返回一个值,并且应用程序不能在没有该返回值的情况下简单地继续。但是,至少在理论上必须有一种解决方法:

如果 UI 库提供了一种使用带返回值的模态对话框的方法,那么该库还必须实现一种方法来暂停当前线程并在另一个线程中显示模态对话框,以便可以与模态对话框进行交互。这甚至适用于单线程 UI(这似乎是标准)。例如,在 Java Swing 中,事件调度线程 (ETD) 提供了createSecondaryLoop()Swing 本身使用的方法来实现带有返回值的模式对话框。通常这些方法也会将 UI 控制移动到新线程,这样背景窗口就不会被冻结。这甚至适用于 Windows 资源管理器,如此截屏所示(视频在模式对话框打开时在后台播放):

我们也可以使用该功能。一般的做法是:

  • 拦截将创建模态对话框的调用
  • 使用 UI 库自带的功能暂停当前线程并将 UI 控件移动到新线程
  • 创建并显示等效的非模态对话框
  • 当对话框关闭时,检索返回值的数据
  • 使用 UI 库自带的功能恢复原来的 UI 线程
  • 从非模态对话框返回数据

Soc*_*owi 4

Harrymc指出,AutoHotKey 可能能够取消模式化窗口,这让我想到了这个问题,其中包含以下 AHK 脚本(有一个小语法错误,在下面的版本中已修复):

^e::
MouseGetPos,,, WindowUnderMouse
WinSet, Style, -0x8000000, ahk_id %WindowUnderMouse%
return
Run Code Online (Sandbox Code Playgroud)

安装 AutoHotKey 后,将此脚本保存在 中file.ahk,双击该文件(或右键单击并选择Run Script)。如果您有一个模式对话框并且想要与其父/背景窗口交互,请将鼠标悬停在父/背景窗口上并按CtrlE(这就是^e::) 所代表的;背景/父窗口现在应该再次对交互做出反应,而无需关闭模式对话框。

“样式”记录在此处-0x8000000被记录为

WS_DISABLED| 0x8000000| +/- 禁用。创建一个最初被禁用的窗口。