The cost of continuously-visible affordances with dynamic states

Date:January 22, 2007 / year-entry #23
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20070122-05/?p=28323
Comments:    18
Summary:Serge Wautier asks, "Why are the copy/cut/paste buttons not disabled when there's nothing to copy/cut/paste?", noting that the back/forward buttons do disable themselves when navigation is not possible in that direction. To get to this question, we'll first go back in time a bit to a world without toolbars. In those early days, these dynamic...

Serge Wautier asks, "Why are the copy/cut/paste buttons not disabled when there's nothing to copy/cut/paste?", noting that the back/forward buttons do disable themselves when navigation is not possible in that direction.

To get to this question, we'll first go back in time a bit to a world without toolbars. In those early days, these dynamic options such as copy/cut/paste appeared solely on the Edit menu. Since the contents of Edit menu were visible only when the user clicked on it, the cut/copy/paste options needed to be updated only when the menu was visible. In other words, during WM_INITMENUPOPUP handling.

This is also why it is somewhat risky to post WM_COMMAND messages which correspond to a menu item to a window which is not prepared for it. The only way an end-user can generate that WM_COMMAND message is by going through the menu: clicking the top-level menu to show the drop-down menu, then clicking on the menu item itself. Most programs do not maintain the menu item states when the menu is closed since there's no point in updating something the user can't see. Instead, they do it only in response to the WM_INITMENUPOP message. Lazy evaluation means that the user doesn't pay for something until they use it. In this case, paying for the cost of calculating whether the menu item should be enabled or not. Depending on the program, calculating whether a menu item should be enabled can turn out to be rather expensive, so it's natural to avoid doing it whenever possible. ("I can do nothing really fast.")

When toolbars showed up, things got more complicated. Now, the affordances are visible all the time, right there in the toolbar. How do you update something continuously without destroying performance?

The navigation buttons disable and enable themselves dynamically because the conditions that control their state satisfy several handy criteria.

  • The program knows when the state has potentially changed. (The program maintains the navigation history, so it knows that the button states need to be recalculated only when a navigation occurs.)
  • Computing the state is relatively cheap. (All the program has to check is whether there is a previous and next page in the navigation history Since the navigation history is typically maintained as a list, this is easy to do.)
  • They change in proportion to user activity within the program. (Each state change can be tied to a user's actions. They don't change on their own.)
  • They change rarely. (Users do not navigate a hundred times per second.)

Since the program knows when the navigation stack has changed, it doesn't have to waste its time updating the button states when nothing has changed. Since recalculating the state is relatively cheap, the end user will not see the main user interface slow down while the program goes off to determine the new button state after each navigation. And finally, the state changes rarely, so that this cheap calculation does not multiply into an expensive one.

The copy/cut/paste buttons, on the other hand, often fail to meet these criteria. First, the copy and cut options:

  • The program knows when the state has potentially changed. (Whenever the selection changes.) — good
  • Computing the state is not always cheap. (For example, determining whether an item in Explorer can be cut or copied requires talking to its namespace handler, which can mean loading a DLL. If the item on the clipboard is a file on the network, you may have to access a computer halfway around the world.) — often bad
  • It changes in proportion to user activity within the program. (Each state change can be traced to the user changing the selection.)
  • They change with high frequency. (Dragging a rectangle to make a group selection changes the selection each time the rectangle encloses a new item.) — bad

Paste is even worse.

  • The program doesn't know when the state has potentially changed. (The clipboard can change at any time. Yes, the program could install a clipboard viewer, but that comes with its own performance problems.) — bad
  • Computing the state is not cheap. (The program has to open the clipboard, retrieve the data on it, and see whether it is in a format that can be pasted. If the clipboard contents are delay-rendered, then the constant probing of the clipboard defeats the purpose of delay-rendered clipboard data, which is to defer the cost of generating clipboard data until the user actually wants it. For Explorer, it's even worse, because it has to take the data and ask the selected item whether it can accept the paste. Doing this means talking to the namespace handler, which can mean loading a DLL. And if the file on the clipboard is on the network, the paste handler may need to open the file to see if it is in a format that can be pasted.) — bad
  • It can change out of proportion to user activity. (Any time any other program copies something to the clipboard, the toolbar has to update itself. Then can happen even when the user is not using the program that has the toolbar! Imagine if Explorer started saturating your network because you copied a lot of UNC paths to the clipboard while editing some text file.) — bad
  • The frequency of change is unknown. (The clipboard is a shared resource, and who knows what other people might be using it for.) — bad

This is one of those balancing acts you have to do when designing a program. How much performance degredation are you willing to make the user suffer through in order to get a feature they may never even notice (except possibly in a bad way)?


Comments (18)
  1. Peter Ritchie says:

    It’s not clear; but this doesn’t apply to cut/copy/paste buttons in the general case, just to the affordances in Windows Explorer.

    There’s no reason why a simple application can’t update their cut & copy buttons in real-time.  A paste button would be more work; but, as a clipboard "viewer" it doesn’t actually have to render anything, just check for supported formats when it’s notified of render messages.

    Sounds like you’ve explained where things like WM_CLIPBOARDUPDATE and AddClipboardFormatListener were added to Vista…

  2. Koro says:

    The Windows Media Player shell extension opens an .avi file everytime it’s selected in explorer in order to display the movie length and resolution in the status bar. On my old computer this resulted in ~10sec 100% CPU usage peaks everytime I selected one.

    It was also hard to select and delete them too, since they were being "used" by the shell extension.

  3. Very nice essay.  I nice investigation of cost/benefit from the inside.  The comparison to why navigation does work is really good at illustrating the specifics of the differences between the two assessments.

    I have a feeling the quote "I can do nothing really fast." is going to stick with me in future assessments :).

    @Koro, I’ve had similar problems.  Could this be an example of what would be happending if copy/paste were disabled/enabled in real time?  Methinks it is.

  4. swautier says:

    Raymond, thanks for such a detailed explanation.

    I don’t buy every "bad" conclusion you draw but of course your overall point is valid even if I remove these ones.

    BTW, I learned a new word today: affordance. :)

  5. Eric TF Bat says:

    One text editor, TextPad, has a set of clipboard tool buttons that do change in realtime.  I don’t believe it bothers checking the format of the data in the clipboard (perhaps they figured the cost wasn’t worth the minimal usefulness) but it does enable and disable Cut, Copy and Paste according to the current state of the selection.  The result?  An irritating and initially-inexplicable flicker out of the corner of your eye, making you think something is buggy until you eventually figure out what’s going on.  Verdict: dumb idea.

  6. Jeremy Morton says:

    Textpad does disable the Paste button when the clipboard’s format isn’t text [for example, when you hit PrtScn]. But a text editor scenario does further restrict when state changes and valid clipboard data and may make it worthwhile to do. OTOH Word can potentially paste most any clipboard format, so it may not be worthwhile there, as it isn’t in Explorer.

  7. steveg says:

    I wonder if there’s a usability issue in there as well, perhaps it’s better to have the troika of clipboard buttons always visible and enabled because they are close to the Most Useful Thing To Know (on a PC), and possibly The Only Thing Some People Know (on a PC) and therefore best not to confuse them.

    As an example the lady who sits near me couldn’t work out how to Copy in IE7 last week because it doesn’t have Copy on the toolbar by default — if Paste had been visible and grayed out I might have been asked "Why is paste grayed out".

    Anyways, the moral of the story is sometimes it’s not worth updating the user interface if it degrades the user experience…

  8. Nick says:

    Thanks for the post.

    Off-topic, but regarding the clipboard:  Has anyone ever suggested creating a more advanced clipboard manager?  Something that retains a history of clipboard items with the ability to place an old item back into the ‘current’ buffer?  I don’t know how many times I’ve wished the clipboard stored old stuff.

    This would be a *great* addition to Windows or as a PowerToy for XP/Vista.

    (Yes, I know you can pay to do it with Clipmate [http://www.thornsoft.com/clipmate7.htm], but it’d be nice as a part of Windows).

  9. Robert says:

    WordPad seems to have solved this in a different way. Even when it is not active it updates the paste button when the mouse is over one of the toolbar buttons.

  10. Phylyp says:

    Nice writeup on the differences between the cost of displaying internal state and external state

  11. nikos says:

    although i agree that "paste" activation handling is more expensive for shell formats, with good (sensible) idle processing and using IsClipboardFormatAvailable(SHIDLIST) the cost is negligible, this is pentium era after all :)

    having said that i’ve noticed that xplorer2 (which implements the above UI strategy) does get the occasional cpu usage spike … nothing to write home about though

  12. Peter Ritchie says:

    @Nick: do you mean something like the Office Clipboard?

  13. Steve Wake says:

    Since the clipboard is an internal service, then should not any program making a change to it’s state be able to send a notification to all other programs that this state has change (e.g. a WM_NOTIFY_CLIPBOARD…) message, and let other programs decide to handle it or not (doing a query on the new formats available?)

    [“Yes, the program could install a clipboard viewer, but that comes with its own performance problems.” And that still doesn’t fix the “frequency of update is unknown”. A program that manipulates the clipboard can cause Explorer to consume a lot of CPU. I would think most people would consider that a bug not a feature. -Raymond]
  14. Steve Wake says:

    Actually, I meant to say the clipboard service sends the norification to other applications (including the one who made the original notification)…

  15. codekaizen says:

    swautier:

    The term ‘affordances’ originated with a different intent than is used here.

    Donald Norman explains here:

    http://www.jnd.org/dn.mss/affordances_and.html

    and here:

    http://www.jnd.org/dn.mss/affordance_conv.html

    Donald’s book, "Design of Everyday Things" somewhat popularized the term, and due to it’s popularity, the meaning has become skewed. This is too bad, since now it obscures the principles of graphical UI design which the skewed usage intends to mean.

    UI gestures are often consistent metaphor and convention, with word labeling to get the perceived affordance across. This is different from actual, or real, affordance. In UI design, these are often separate, since you don’t actually "click" on a screen or "move" the screen when dragging a UI element (though the Wiimote emulates this – would this be a ‘proxied’ affordance?).

  16. Neil says:

    "the frequency of update is unknown"

    I can’t see how I can put something on the clipboard faster than (say) the PrtSc key autorepeats (if it does) and if some app is constantly rewriting the clipboard then the format change notifications will bring all of my remote desktops to a crawl and it deserves to die.

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