Rotating the Z-order

Date:August 26, 2003 / year-entry #33
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20030826-00/?p=42793
Comments:    1
Summary:Sometimes you run into a conflict where you need the controls laid out in one Z-order to get hit-testing to work, but need a different order to get keyboard TAB order working. For example, consider this dialog template, which has been simplified for expository purposes. //////////////////////////////////////////////////////////////////////// // // Note: The ListView control has to be...

Sometimes you run into a conflict where you need the controls laid out in one Z-order to get hit-testing to work, but need a different order to get keyboard TAB order working.

For example, consider this dialog template, which has been simplified for expository purposes.

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

The dialog looks like this:

  _______  _______
 / Tab   \/ Tab   \_____________________
|                                       \
| +-[List]-----------------------------+ |
| |                                    | |
| |                                    | |
| |                                    | |
| |                                    | |
| +------------------------------------+ |
|________________________________________|


[ Import ]   [ Export ]  [ Remove ]

                                 [ Close ]

Drag/drop will call WindowFromPoint() to determine which window receives the drop. The window closest to the top of the Z-order (towards the beginning of the dialog template) will be chosen.

We want drops to go to the listview, not the tab control, so the ListView (IDC_LIST) needs to go ahead of the Tab control (IDC_TAB).

However, doing this breaks accessibility, because the tab order follows the Z-order, too. Consequently, the Tab order on the dialog is

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

This is an undesirable tab order, since it causes focus to jump upwards (from List to Tab). To get the tab order right, you need to put Tab before List.

This is where rotation comes in.

Start by putting the controls on the page in the order necessary for tabbing.

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

Recall that the tab order is circular. When you are on the last control and hit TAB, you go to the first one. So you really should view the tab order as a circle:

   /-->  Tab  ---\
   |             |
  Close          v
   ^            List
   |             |
  Remove         v
   ^            Import
   |             |
   \-- Export <--/

Once you view it this way, you realize that you can rotate the circle and the tab order remains unchanged. So let's rotate it so List comes first, since we need List to come first in the Z-order.

   /-->  List ---\
   |             |
  Tab            v
   ^            Import
   |             |
  Close          v
   ^            Export
   |             |
   \-- Remove <--/

Now cut the circle open, yielding the linear diagram:

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

This gives us our final dialog template:

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

Now you get the best of both worlds. List is at the top of the Z-order, and the tab order is still correct.


Comments (1)
  1. Dmitriy Zaslavskiy says:

    This is cute, but only works if you have only one such conflict

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index