有一次,我在帮助一家软件开发商研究他们应用程序中的一个兼容性 Bug。通过这次研究,我想写一篇文章来讲讲窗口相关的细节知识。

这是一个安装包程序,在安装的某个时间点出现了错误,开发商希望能够显示一个错误对话框,当他们调用 DialogBox 的时候并没有传递安装包主程序窗口作为它的父窗口参数(hwndParent),而是为了方便,他们直接调用了 GetForegroundWindow() 并作为父窗口传入。

这样做是有问题的,我还看到在其他案例中,有人会尝试使用 GetTopWindow(0) 来作为父窗口。

碰巧的是,当时前台窗口是任务管理器,因为我已切换到任务管理器以查看其安装程序运行时的各种统计信息。

至此,我希望你能看到这是怎么一回事了: 他们传递了任务管理器窗口作为他们的安装包程序窗口的所有者,并且由于模式对话框禁用了所有者,他们最终禁用了任务管理器。

同时,他们的安装程序窗口仍然处于启用状态,因此如果我想,我可以单击”取消”按钮,这将导致一个所谓的 “stack without support” 问题。

现在我无法从任务管理器终止他们的安装程序进程,因为他们无意中禁用了任务管理器。

但是,为什么程序员还是选择使用前台窗口呢?一种可能性是程序员对窗口体系的一个执念:

> 我们必须传递一个窗口
> 前台窗口是一个窗口
> 所以,我们必须传入前台窗口

另一种可能性是他们故意这样做,以确保他们的错误消息能获取到当前的输入焦点。
因为他们的程序是人类历史上最重要的程序。不幸的是,我经常看到这种情况。

那些认为他们的程序如此重要的人,以至于他们会滥用系统的其余部分来获得他们想要的东西,而不仅仅是等待轮到他们。

当然,这些人也没有意识到,将窗口设置为用户界面的所有者会产生自己的问题。

如前所述,如果你使用前台窗口,则你会禁用了一个随机程序。
更重要的是,你现在已经连接了两个输入队列,并将你的命运联系在一起。如果拥有前景窗口的程序停止响应消息,则程序也将停止响应消息。

但我想说的是,这样做主要是你太粗鲁了: 你拿走了别人的窗户,开始表现得好像你拥有这个地方一样。
这就像在电话簿中查找某人的地址并将其用作自己的地址一样。
那不是你的房子,那不是你的窗户。

总结

我们需要做一个 Windows 世界的守法公民: 我们的程序不可以影响用户的正常操作,也不可以影响其他的程序。
拓扑梅尔智慧办公平台 (TopomelBox) 就一直将这条铁律浇筑在每时每刻的开发中。
我们深知,我们的一生是如此短暂,TopomelBox 的目标是:帮助用户高效完成工作任务,轻轻的来,轻轻的走,不给用户增加一丝心智负担。

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Don’t just grab the foreground window and host UI on it》

最近我写了个东西

正如你们所知道的,拓扑梅尔智慧办公平台(TopomelBox)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

打开网易新闻 查看更多图片