翻译 《The Old New Thing》 - Rotating the Z-order

Rotating the Z-order - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20030826-00/?p=42793

Raymond Chen 2003年8月26日

简要

《Rotating the Z-order - The Old New Thing》,由Raymond Chen在2003年8月26日发表。文章讨论了在设计对话框时可能会遇到的一个问题:为了使点击测试(hit-testing)工作正常,控件需要按照一种Z顺序排列,但为了使键盘的Tab顺序正确,又需要另一种顺序。文章通过一个简化的对话框模板示例来解释这个问题,并提出了一种解决方案。


有时候你会碰到这样的情况:为了让点击测试工作正常,你需要按照一种Z顺序排列控件,但为了让键盘的Tab顺序工作正常,你又需要另一种顺序。

例如,看看这个为了说明问题而简化的对话框模板。

cpp 复制代码
//
//  Note: The ListView control has to be listed BEFORE the tab control in
//  order for drag-drop to work properly.
//
IDD_MAIN DIALOGEX  0, 0, 335, 270
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
                    | DS_CONTEXTHELP | DS_SHELLFONT
CAPTION "Blah blah"
FONT 8, "MS Shell Dlg"
BEGIN
    CONTROL         "List",IDC_LIST,WC_LISTVIEW,LVS_REPORT |
                    WS_BORDER | WS_TABSTOP |
                    LVS_SHOWSELALWAYS,15,46,305,111
    CONTROL         "Tab",IDC_TAB,WC_TABCONTROL,
                    WS_TABSTOP,7,24,321,141
    PUSHBUTTON      "&Import...",IDC_IMPORT,7,172,51,14
    PUSHBUTTON      "&Export...",IDC_EXPORT,62,172,51,14
    PUSHBUTTON      "&Remove",IDC_REMOVE,117,172,51,14
    DEFPUSHBUTTON   "&Close",IDOK,277,249,51,14
END

对话框看起来是这样的:

复制代码
  _______  _______
 / Tab   \/ Tab   \_____________________
|                                       \
| +-[List]-----------------------------+ |
| |                                    | |
| |                                    | |
| |                                    | |
| |                                    | |
| +------------------------------------+ |
|________________________________________|
[ Import ]   [ Export ]  [ Remove ]  [ Close ]

拖放操作会调用WindowFromPoint()来确定哪个窗口接收放置。Z顺序最顶端的窗口(在对话框模板的开始处)会被选中。

我们希望放置操作到ListView,而不是Tab控件,因此ListView(IDC_LIST)需要排在Tab控件(IDC_TAB)之前。

然而,这样做破坏了可访问性,因为Tab顺序也遵循Z顺序。因此,对话框上的Tab顺序是:

List -> Tab -> Import -> Export -> Remove -> Close

这是一个不理想的Tab顺序,因为它导致焦点向上跳转(从List到Tab)。为了使Tab顺序正确,你需要将Tab放在List之前。

这就是旋转发挥作用的地方。

首先,按照Tab顺序在页面上放置控件。

Tab -> List -> Import -> Export -> Remove -> Close

记住,Tab顺序是循环的。当你在最后一个控件上按下Tab键时,你会跳转到第一个控件。所以你实际上应该将Tab顺序视为一个圆:

复制代码
   /-->  Tab  ---\
   |             |
  Close          v
   ^            List
   |             |
  Remove         v
   ^            Import
   |             |
   \-- Export <--/

一旦你这样看待它,你就会意识到你可以旋转这个圆,而Tab顺序仍然不变。所以让我们旋转它,让List首先出现,因为我们需要List在Z顺序中排在最前面。

复制代码
复制代码
   /-->  List ---\
   |             |
  Tab            v
   ^            Import
   |             |
  Close          v
   ^            Export
   |             |
   \-- Remove <--/

现在,将圆切开,得到线性图:

复制代码
List -> Import -> Export -> Remove -> Close -> Tab

这给了我们最终的对话框模板:

cpp 复制代码
//
//  Note: The ListView control has to be listed BEFORE the tab control in
//  order for drag-drop to work properly.
//
IDD_MAIN DIALOGEX  0, 0, 335, 270
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
                    | DS_CONTEXTHELP | DS_SHELLFONT
CAPTION "Blah blah"
FONT 8, "MS Shell Dlg"
BEGIN
    CONTROL         "List",IDC_LIST,WC_LISTVIEW,LVS_REPORT |
                    WS_BORDER | WS_TABSTOP |
                    LVS_SHOWSELALWAYS,15,46,305,111
    PUSHBUTTON      "&Import...",IDC_IMPORT,7,172,51,14
    PUSHBUTTON      "&Export...",IDC_EXPORT,62,172,51,14
    PUSHBUTTON      "&Remove",IDC_REMOVE,117,172,51,14
    DEFPUSHBUTTON   "&Close",IDOK,277,249,51,14
    CONTROL         "Tab",IDC_TAB,WC_TABCONTROL,
                    WS_TABSTOP,7,24,321,141
END

现在你得到了两全其美的结果。List位于Z顺序的顶端,而Tab顺序仍然是正确的。✌

相关推荐
q***925120 小时前
Windows上安装Go并配置环境变量(图文步骤)
开发语言·windows·golang
凭栏落花侧1 天前
打印机脱机状态应该怎么处理
windows
q***57741 天前
MySQL 实验1:Windows 环境下 MySQL5.5 安装与配置
windows·mysql·adb
q***31831 天前
Windows安装Rust环境(详细教程)
开发语言·windows·rust
q***82911 天前
windows同时安装两个不同版本的Mysql
windows·mysql·adb
dntktop1 天前
搜索+计算+插件…这个“全能管家”让你告别80%的桌面图标
运维·windows·自动化·编辑器
h***34631 天前
Redis安装教程(Windows版本)
数据库·windows·redis
a***13141 天前
redis存取list集合
windows·redis·list
lpfasd1231 天前
Windows下使用nvm-windows管理Node.js版本及npm配置全指南
windows·npm·node.js
e***75391 天前
在 Windows 上生成本地 SSL 证书并使用 HTTPS 访问本地 Nginx 服务器
windows·https·ssl