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

 

Rotating the Z-order - The Old New Thing (microsoft.com)icon-default.png?t=N7T8https://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顺序工作正常,你又需要另一种顺序。

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


//
//  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

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


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

相关推荐

  1. Qt :Ordered Map

    2024-03-29 05:20:04       28 阅读
  2. ORDER BY FIELD

    2024-03-29 05:20:04       27 阅读
  3. ORDER BY和ROW_NUMBER() OVER (ORDER BY ...)区别?SQL

    2024-03-29 05:20:04       62 阅读
  4. MySQL ORDER BY 实现原理

    2024-03-29 05:20:04       53 阅读
  5. mysql order by 排序原理

    2024-03-29 05:20:04       41 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-29 05:20:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-29 05:20:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-29 05:20:04       82 阅读
  4. Python语言-面向对象

    2024-03-29 05:20:04       91 阅读

热门阅读

  1. Docker版本:18.06.1安装

    2024-03-29 05:20:04       35 阅读
  2. Debian GNU/Linux 安装docker与docker compose

    2024-03-29 05:20:04       33 阅读
  3. vue3中onUnmounted详解

    2024-03-29 05:20:04       40 阅读
  4. Linux(CentOS)/Windows-C++ 云备份项目(结项,项目总结)

    2024-03-29 05:20:04       41 阅读
  5. Kotlin:@JvmOverloads注解

    2024-03-29 05:20:04       41 阅读
  6. 3.28 c++

    2024-03-29 05:20:04       37 阅读
  7. NatCat使用说明

    2024-03-29 05:20:04       39 阅读
  8. Yarn的安装和使用

    2024-03-29 05:20:04       42 阅读
  9. VUE3——setup介绍

    2024-03-29 05:20:04       38 阅读