Starting with Windows 2000, keyboard indicators such as underlined accelerators and focus rectangles (collectively known as “keyboard cues”) are hidden by default, and are revealed only when you start using the keyboard. You can control this behavior from the Desktop Control Panel, under Appearance, Effects, “Hide underlined letters for keyboard navigation until I press the Alt key”.
Note that this setting actually controls both underlined letters and focus rectangles, even though the text describes only one of the effects. Underlines are hidden until you press the Alt key, and focus rectangles are hidden until you either press the Alt key or press the Tab key.
Here’s how it works.
There are three UI state mesages:
WM_CHANGEUISTATE
,
WM_QUERYUISTATE
and
WM_UPDATEUISTATE
.
The third one is, in my opinion, a misnomer.
It really should be called something like WM_UISTATECHANGED
since it is a notification that something has happened, not
a message that you send to cause something to happen.
When a dialog box or menu is displayed via a mouse click,
keyboard cues are hidden; if the dialog box or menu was displayed
via a keypress, then keyboard cues are visible.
This decision is made by sending a
WM_CHANGEUISTATE
message to the root window with the
UIS_INITIALIZE
flag.
This is done automatically by the dialog manager, but if you’re
doing your own custom windows, you’ll have to send it yourself.
The WM_CHANGEUISTATE
message bubbles up to the
top-level window, which changes the window UI state accordingly,
then broadcasts a WM_UPDATEUISTATE
message to all its child windows
to notify them that the state has changed.
(Of course, if the WM_CHANGEUISTATE
message has no effect—for
example, hiding something that is already hidden—then the
WM_UPDATEUISTATE
message is optimized out since the entire operation
is a no-op.)
When a window that draws keyboard cues
receives a WM_UPDATEUISTATE
message,
it typically invalidates itself so that the cues can be redrawn/erased,
depending on the new state.
At drawing time, a window that draws keyboard cues can use the
WM_QUERYUISTATE
message to determine which keyboard cues are
visible and which are hidden, and draw its content accordingly.
If focus rectangles are hidden, then the window should skip the call
to the DrawFocusRect
function.
If keyboard underlines are hidden, then the window suppresses
underlines in its text drawing. If the window uses
the DrawText
function,
it can pass the DT_HIDEPREFIX
flag
to suppress the underlines.
If you are responding to
the WM_DRAWITEM
message, then you should check for the
ODS_NOACCEL
and ODS_NOFOCUSRECT
flags
to determine
whether
you should draw an underline accelerator or a focus rectangle.
Finally, during execution you may discover that the user has used
the keyboard to perform navigation within your control.
For example, the listview control may have noticed that the user has used
the arrow keys to change the selected item.
When this happens, the control sends itself a WM_CHANGEUISTATE
specifying
which keyboard cues should be revealed.
As noted above, the WM_CHANGEUISTATE
message eventually causes all the
windows in the window tree to receive a WM_UPDATEUISTATE
message
if their states need to change.
The IsDialogMessage
function
sends
WM_CHANGEUISTATE
messages as appropriate, so dialog boxes
and anybody else who uses IsDialogMessage
gets
keyboard-cues tracking for free.
0 comments