Holy cow, I wrote a book!
The commentary after
my entry on taskbar grouping
drifted into people asking for still more features in taskbar
Writing the code is the easy part.
Designing a feature is hard.
You have several audiences to consider.
It's not just about the alpha geeks;
you have to worry about the grandmothers,
the office workers,
the IT departments.
They all have different needs.
Sometimes a feature that pleases one group
So let's look at some of the issues surrounding the
proposed feature of allowing users to selectively ungroup
items in the taskbar.
One issue with selective grouping is
deciding the scope of the feature.
Suppose the user ungroups Internet Explorer,
then closes all the IE windows,
then opens two new IE windows:
Do the new ones group?
If so, then you now have an invisible setting.
How do you configure grouping for programs that aren't running?
(How do you configure something that you can't see?)
Suppose you've figured that out. That's fine for the alpha geeks,
but what about grandma?
"The Internet is all disorganized."
"What do you mean?"
"All my Internet windows are all disorganized."
"Can you explain a little more?"
"My taskbar used to be nice and organized,
but now the Internet parts are disorganized and spread out all over the place.
It used to be nice and neat.
I don't know how it happened.
I hate the Internet, it's always messing up my computer."
What is the UI for selective ungrouping?
Anything that is on a context menu will be executed
accidentally by tens of thousands of people due to mouse twitching.
Putting the regroup onto the context menu isn't
necessarily good enough because those people don't even
realize it was a context menu that did it. It was just a mouse twitch.
Mouse twitches cause all sorts of problems.
accidentally dock their taskbar vertically;
accidentally resize their taskbar to half the size of the screen.
Do not underestimate the havoc that can be caused by mouse twitching.
Soon people will want to do arbitrary grouping.
"I want to group this command prompt,
that notepad window, and this calc window together."
What about selective ungrouping?
"I have this group of 10 windows,
but I want to ungroup just 2 of them,
leaving the other 8 grouped together."
Once you have selective/arbitrary grouping,
how do you handle new windows? What group do they go into?
Remember: Once you decide, "No, that's too much,"
there will be thousands of people cursing you for not doing enough.
Where do you draw the line?
And also remember that each feature you add will cost you another
feature somewhere else. Manpower isn't free.
But wait, the job has just begin.
Next, you get to sit down and do the usability testing.
Soon you'll discover that everything you assumed
to be true is completely wrong,
and you have to go back to the drawing board.
Eventually, you might conclude that you over-designed the feature
and you should go back to the simple on/off switch.
Wait, you're still not done.
Now you have to bounce this feature off corporate IT managers.
They will probably tear it to shreds too.
In particular, they're going to demand things like
remote administration and the ability to force the
setting on or off across their entire company
from a central location.
(And woe unto you if you chose something more complicated
than an on/off switch: Now you have to be able to deploy
that complex setting across tens of thousands of computers - some
of which may be connected to the corporate network via slow
Those are just some of the issues involved in designing a feature.
Sometimes I think it's a miracle that features happen at all!
(Disclaimer: I'm not saying this is how the grouping feature
actually came to be. I just used it as a starting point for
For another perspective, you can check out
KC Lemson's discussion of the feature-design
process a few days ago under the topic
There's no such thing as a simple feature.
I find it ironic when people complain
that Calc and Notepad haven't changed.
In fact, both programs have changed.
(Notepad gained some additional menu and status bar options.
Calc got a severe workover.)
I wouldn't be surprised if these are
the same people who complain,
"Why does Microsoft spend all its effort on making Windows
'look cool'? They should spend all their efforts on
making technical improvements and just stop making visual improvements."
And with Calc, that's exactly what happened:
Massive technical improvements.
No visual improvement.
And nobody noticed.
In fact, the complaints just keep coming.
"Look at Calc, same as it always was."
The innards of Calc - the arithmetic engine - was completely
thrown away and rewritten from scratch.
The standard IEEE floating point library
was replaced with
an arbitrary-precision arithmetic library.
This was done after people kept writing
ha-ha articles about how Calc couldn't do decimal
arithmetic correctly, that for example computing
10.21 - 10.2 resulted in 0.0100000000000016.
(These all came from people who didn't understand
how computers handle floating point. I have a future entry
planned to go into floating point
representations in more detail.)
Today, Calc's internal computations are done with infinite
precision for basic operations (addition, subtraction, multiplication,
division) and 32 digits of precision for advanced operations
(square root, transcendental operators).
Try it: 1 / 3 * 10000000000 - 3333333333 =.
The result is one third exactly. Type 1/x - 3 =
and you get zero back.
(Of course, if you don't believe that, then repeat the sequence
"* 10000000000 - 3333333333 =" until you're bored and notice
that the answer always comes back as 0.33333333333333333333333333333333.
If it were fixed-precision, then the 3's would eventually stop coming.)
Thirty-two positions of precision for inexact results not good enough?
Power Calculator PowerToy uses the same arithmetic engine as Calc
and lets you crank the precision to an unimaginable 512 digits.
Anyway, my point is that - whether you like it or not - if you
don't change the UI, nobody notices.
That's so much effort is spent on new UI.
Okay I know I'm going to get into a lot of trouble for even
bringing up this topic...
This past weekend,
Ulf Harnhammar discovered two buffer overflow and two
directory traversal vulnerabilities in LHA,
a library of data compression functions.
Since the code for this is public,
it has been copied all over the place.
At least one commercial archive management program and
at least one commercial mail antivirus program are vulnerable.
A denial of service attack is already under way against the mail
antivirus program; all you have to do is attach a
malformed LHA file to a
message, causing the scanner to crash when it attempts
to scan the attachment.
When the administrator restarts the mail server, the scanner
will resume where it left off... and crash again.
(Somebody with more time on their hands could craft a more
clever LHA file attack that takes over the mail server itself.)
The fact that the code itself was public meant that everybody
didn't have to write their own LHA functions. This is a good thing.
However, it also means that everybody has the same security vulnerabilities.
This is a bad thing.
So we have one bug that can take down large numbers of
machines, even though they're all running different software.
How do you track all the versions?
Is there a solution to this?
Is it even a problem?
In a comment,
Darrell Norton asked
for a "View in Mozilla" option for Internet Explorer.
You can already do this.
context menu extension mechanism
has been in MSDN for years.
Let me show you how you can create this extension yourself.
First, create the following registry key:
[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\View in Mozilla]
Of course, you need to change C:\some\path\to to an actual path.
How did I know to do this?
Because steps 1, 2 and 3 in the "Implementation Steps" section tell
me (1) what key to create, (2) what to set the default value to, and
(3) what to set Contexts to.
I chose a Context value of 1, which means "Default".
Okay, now to write the script ViewInMozilla.htm.
Well, the documentation says that I can access context
property of the
So let's start with that.
Okay, let's run this puppy. Launch IE, right-click on a blank
space in the web page, select "View in Mozilla", and you get...
Woo-hoo! This is a major accomplishment: Something happened at all.
Doing things in small steps makes it easy to identify where a problem is.
If we had run full steam ahead to completion
and then it didn't work, we wouldn't have
known whether it was due to a bug in the script, a bad registration, a bad
Now that I have the menu arguments, I can use that
to suck out information about the item that the context menu
applies to. Let's try this:
Woo-hoo, now it gives me the URL. Almost there. All that's
left to do is to run a program with that URL as the command line
var shell = new ActiveXObject("WScript.Shell");
shell.run("mozilla \"" + external.menuArguments.document.URL + "\"");
Now you too can create Internet Explorer context menu extensions.
In fact, go ahead and do it, since Darrell asked for it:
Create an Internet Explorer
context menu extension that operates on anchors and opens the
linked-to page in Mozilla.
something similar for zooming.)
The keyboard shortcut for "Minimize All" is
The keyboard shortcut for "Show Desktop" is
How are they different?
"Minimize All" is easier to describe.
It minimizes all the windows that support the "Minimize" command.
You can minimize a window by selecting "Minimize" from its System menu,
or by clicking the
button in the title bar.
So "Minimize All" is effectively the same as going to each window
that is open and clicking the Minimize button.
If there is a window that doesn't have a Minimize button, then it is
"Show Desktop" takes "Minimize All" one step further.
After minimizing all the windows that can be minimized,
it then takes the desktop and "raises" it to the top of the
window stack so that no other windows cover it.
(Well, okay, topmost windows continue to cover it.)
So "Show Desktop" manages to get a few more windows out of your way
than "Minimize All".
Note, however, that when you return the desktop to its normal
state (either by selecting "Show Open Windows" or just by switching
to another window), all the un-minimizeable windows come back
because the desktop has "lowered" itself back to the bottom of the
When do you put "..." after a button or menu?
For example, some menus say "Save as..."
and some buttons say "Customize...".
What is the rule for dots?
Many people believe that the rule for dots is
"If it's going to display a dialog, then you need dots."
This is a misapprehension.
The rules are spelled out in the
Windows User Interface Design Specifications and Guidelines
(what a mouthful). Scroll down to "Ellipses".
I could repeat what's written there, or I could just tell you to read it.
I'm going to tell you to read it.
Okay, maybe I'm going to repeat what's written there, but briefly:
Use an ellipsis if the command requires additional information
before it can be performed.
Sometimes the dialog box is the command itself, such as "About"
or "Properties". Even though they display a dialog, the dialog
is the result, as opposed to commands like "Print" where
the dialog is collecting additional information prior to the result.
here's another case where you have to watch your destructors.
Yesterday's theme was destructors that run at the wrong time.
Today, we're going to see destructors that don't run at all!
Assume there's an ObjectLock class which
takes a lock in its constructor
and releases it in its destructor.
DWORD ThreadProc(LPVOID p)
... do stuff ...
... do stuff ...
Pretty standard stuff.
The first batch of stuff is done without the lock,
and the second batch is done inside the lock.
When the function returns, the lock is automatically released.
But suppose somebody adds a little code to this function like this:
DWORD ThreadProc(LPVOID p)
... do stuff ...
if (p->cancelled) ExitThread(1);
The code change was just to add an early exit if the object was
But when does that ObjectLock destructor run?
It runs at the return statement, since that's when the
lock goes out of scope. In particular, it is
not run before you call ExitThread.
Result: You left an object locked permanently.
You can imagine how variations on this code could lead to
resource leaks or other problems.
Just because you have
the ASCII table memorized
doesn't mean you know how sorting works.
I remember a bug filed where somebody said that the "sort"
command was sorting underscores incorrectly:
this was claimed to be wrong "because underscore character
follow uppercase letters and precedes lowercase letters".
Well perhaps it does if you think ASCII sorting is the way
sorting should be.
ASCII sorting is so last century.
describes two types of sorting, "word sort" and "string sort".
And both of them sort punctuation before letters.
Remember that there are two types of scrollbars.
One is the standalone scrollbar control.
This one has its own window handle, and consequently
can be given focus and all those other fun things
you can do with window handles.
To manipulate them, pass the handle to the scrollbar
control to the appropriate scrollbar function
(SetScrollInfo, for example)
and pass SB_CTL as the nBar parameter to indicate that
you have a scrollbar control.
The other type is the horizontal or vertical scrollbar
(or both) attached to a window by virtue of having
the WS_HSCROLL and/or WS_VSCROLL style.
These are nonclient scrollbars and are not controls.
They are just decorations added to some other window.
You can't give them focus since they aren't windows
in their own right.
To manipulate them, pass the handle to the containing window
to the appropriate scrollbar function
and pass SB_HORZ or SB_VERT as the nBar parameter to indicate that
you want to manipulate the nonclient horizontal or vertical scrollbar.
I'm writing this down since some people seem to miss
the distinction between these two cases.
Social researchers dissect the interactions and unveil the
unwritten rules that govern
British pub etiquette.