一个小问题
有时候有这么个问题:你需要控件保持一种Z序来实现hit-testing,同时你需要另外一种不同的Z序来实现键盘的TAB按键响应的顺序。
举个栗子
考虑下面的对话框模板,这里为了演示目的做了一些简化:
上面的对话框模板将呈现出如下图所示的界面:
Drag/Drop操作将会调用WindowFromPoint来确定是哪一个串口接收到了Drop消息。位于Z序最上方的窗口将会被选中。
如果我们希望Drop消息的接收窗口时列表控件,而不是Tab控件。则列表控件的ID定义(IDC_LIST)需要放在Tab控件之上(IDC_TAB)。
但是,不幸的是,如果这样做的话,将会对易用性带来损伤,因为Tab顺序也是基于Z序的。
下面的Tab顺序可能不是开发者希望看到的:
List -> Tab -> Import -> Export -> Remove -> Close
这在使用者看来会觉得奇怪,因为当使用者按Tab切换控件焦点时,他会看到焦点”向前跳动”(从列表控件调到了Tab控件)。如果想得到预期的Tab切换顺序,就必须将Tab控件放置到列表控件之前。
这就是轮换概念的由来
首先将控件按照期望的Tab顺序放置到对话框上,如下:
Tab -> List -> Import -> Export -> Remove -> Close
还记得吗,Tab顺序是一个环状结构,当输入焦点位于最后一个控件时,此时按下Tab,则输入焦点将会回到第一个控件上。所以,你应该会想象到控件的Tab顺序会像一个环状结构,如下图所示:
现在,将这个环状结构剪开,然后会得到如下的线性顺序:
List -> Import -> Export -> Remove -> Close -> Tab
下面是修改之后的对话框模板:
经过修改之后,我们得到了预期的效果(一颗石头打到了两只鸟)。现在列表控件的Z序位于最上面,而且Tab顺序也是预期的行为。