翻译 《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顺序仍然是正确的。✌

相关推荐
白帽黑客cst4 小时前
网络安全(黑客技术) 最新三个月学习计划
网络·数据结构·windows·学习·安全·web安全·网络安全
YRr YRr4 小时前
在Windows上安装WSL2和Ubuntu 20.04以搭建C++开发环境的详细指南
c++·windows·ubuntu·wsl2
Mac分享吧6 小时前
VMware Fusion虚拟机Mac版 安装Win10系统教程
windows·macos·操作系统·vmware·软件需求·虚拟机·分享软件
空白诗8 小时前
使用 nvm 管理 node 版本:如何在 macOS 和 Windows 上安装使用nvm
windows·macos·node.js·nvm
_道隐_10 小时前
如何在Windows上安装Docker
windows·docker
sukalot10 小时前
windows C++ 并行编程-异步消息块(五)
c++·windows
指间and流年18 小时前
Windows Server2016多用户登录破解
windows
sysin.org1 天前
VMware ESXi 7.0U3q macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025
windows·macos·esxi·bios·oem·网卡驱动·nvme驱动
shuxianshrng1 天前
大气网格化精细化监管监测系统
大数据·服务器·windows·经验分享
晚睡早起₍˄·͈༝·͈˄*₎◞ ̑̑1 天前
苍穹外卖学习笔记(七)
java·windows·笔记·学习·mybatis