关于DS_CONTROL风格的讲解

关于DS_CONTROL风格的讲解

作者:BlogUpdater |  时间:2021-08-27 |  浏览:546 |  评论已关闭 条评论

先来个一句话解释
如果一个对象设置了DS_CONTROL风格,则表示:这个对话框会被视作另一个对话框的子窗口,而不是一个普通的顶层对话框。也即所谓的嵌套对话框。

其实,嵌套对话框并不可怕,也比较常见。你会经常看到一些属性对话框,里面每一个页面都是一个单独的对话框,这些对话框都是作为外部对话框的子窗口。另外,在一些通用对话框中,你也会看到这种嵌套型对话框。如果你观察下记事本里的“另存为”窗口,在窗口底部的额外选项就是一个嵌套窗口。

当在对话框模板中设置了DS_CONTROL风格(或者在一个普通窗口设置WS_EX_CONTROLPARENT扩展风格),就会产生一些新的运行规则介入其中。

首先,对话框的WS_CAPTION和WS_SYSMENU这两个风格都会被忽略。因为设置了DS_CONTROL风格之后,对话框就变为了一个子窗口了,而不是一个顶层窗口,所以它不应该有一个标题栏或者系统菜单栏(因为标准栏和系统菜单是来自于一个外层窗口)。

然后,一些和对话框导航功能相关的函数,例如GetNextDlgTabItem,这个函数在对对话框上的控件进行遍历时,会嵌套地对WS_EX_CONTROLPARENT风格的窗口进行遍历。如果没有设置这个风格,控件搜索会将嵌入的对话框视为一个巨大的控件,而不是其他控件的容器。

当你创建一个带有DS_CONTROL风格的对话框时,你需要使用类似CreateDialogParam这样的创建函数,而不是对话框相关的函数如DialogBoxParam,因为消息循环由外层对话框进行控制,而不是子窗口。

为了避免将对话管理器发送到无限循环中,必须了解递归行为。当你调用GetNextDlgTabItem函数来查询前一个控件时,它会从起始控件开始,遍历对话框上面的所有控件,直到重新回到起点。
如果你忘记将对话框标记为DS_CONTROL,并且焦点起始位于子对话框,则控件枚举将不会递归到子对话框中,因此永远不会找到起点。对话管理器将继续循环,寻找那个起点控制并且永远找不到它,也就是说进入了无限循环。

(即使没有DS_CONTROL,这个问题也存在。如果你从禁用或不可见的控件开始遍历,那么遍历控件将再也找不到起始点,因为在用Tab键浏览对话框时会跳过那些禁用和不可见的控件。)

总结
当对话框程序的焦点位于容器对话框时进行焦点切换,出现界面假死时,可能就是因为这个DS_CONTROL风格的问题。
也算是小技巧一枚吧。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《What is the DS_CONTROL style for?》

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

评论已关闭。