World, Meet Hourglass. Hourglass, World.


Ahh, I can see the ubiquitous hourglass. The hourglass has been around for some time (figuratively speaking, I hope). The original Macintosh had a little clock thing, and Microsoft used the hourglass. Before Windows NT came along, Windows was plagued with the hourglass, due to the single-threaded nature of Windows. Yes, it’s true: Up to and including version 3.1, Windows did not have multithreaded capabilities. And so when that hourglass turned on, you were stuck.

When Windows NT came along, Microsoft added multithreaded and multiprocess support. And with that came a new icon: the pointer/hourglass combination. Here’s this new icon from Windows XP (since I no longer have an old NT box to do a screen capture from):

This unusual form of the hourglass appears primarily when the operating system is working in the background, performing a task, such as starting a program. (In fact, the name of the hourglass in the header files is IDC_APPSTARTING.) If the program has to load a lot of DLLs, the startup can take a good amount of time. The pointer-hourglass icon, then, serves an important purpose: It tells the users, even though it seems like nothing is happening, trust me, that the program is loading. It’s just taking a while. And meanwhile, you users can still do other work.

If the pointer remained a regular pointer with no hourglass, the users would think nothing is happening, especially considering that they can continue working, clicking icons or even trying again to start the program. But if the hourglass were to switch to the standard hourglass, then the slightly more savvy users hoping to continue working might not realize that no, the computer isn’t frozen, and they can do other work.

In addition to the hourglass-pointer combo, Microsoft now supports a per-window hourglass as well. In this case, if your program is doing something that takes a while, and you turn on the hourglass, the hourglass will appear only when the user floats the pointer over your window.

This is a good thing:

RULE

If you’re going to turn on the hourglass, don’t turn it on for the whole system. Only your program is working. If the users move the mouse away from your program, since the system is multitasking, they shouldn’t have to continue seeing the hourglass.

If you’re calling into the API, just use the standard SetCursor function. This function will set the cursor for your windows and no others. And your users will be much happier.

Alternatives to Showing the Hourglass

Even though the hourglass works well, by and large, it is particularly rude, because it seems to be telling the user, “Leave me alone! I’m busy!” We all know what it’s like to walk into a coworker’s office only to be told that she is too busy to speak to us; now the last thing we need is for the computer to tell us this too! Life is difficult enough. Add computers to the picture and it can turn horrendous, right?

So before throwing up the hourglass (or, before choosing to omit the hourglass but never-theless have your program work while unable to receive user input), consider whether your program really can’t receive user input. That is, after all, the purpose of the hourglass: to inform the users that the program is busy and can’t hear them.

Here are two important questions to consider:

  • Can your program perform the operation in the background, allowing the user to continue working (and does it make sense to do so)?

  • Should the user be able to cancel the operation your software is performing?

In some cases, either of these might not make sense. For example, if you’re saving a file to the disk, a cancel operation might not be a good idea, because you might end up with a corrupted file on the disk. But for the first item, regarding doing the work in the background, to be honest, I’m having trouble thinking of an example where you wouldn’t want this. For example, while saving a document, you might not want to allow the user to edit the document. But doing the save in the background isn’t out of the question: You could copy the entire document’s state to a new object and write that object to the file, allowing the user to continue modifying the main object. Then after you’ve finished writing the file, you could delete the copy of the object. This shows, then, that even if you think the task has no reason to be performed in the background, think it through carefully before deciding for sure.

Implementing a Cancel Button

Prior to Windows 2000, the print system in Windows has a strange quirk: If you started a printout and realized the printer was disconnected, and then you canceled the printout (by opening the printer window, right-clicking the document, and choosing Cancel), the document wouldn’t immediately disappear from the printer window! Instead, you would wait, and eventually the document would disappear. Since I haven’t seen the code for the print spooler portion of Windows, I can’t know for sure why this delayed canceling was the case. But I suspect it had to do with waiting for the printer (which, remember, wasn’t hooked up) to respond, and such. Or it might have had to do with the printer window attempting some interprocess communication with the print spooler, and the print spooler polled only occasionally for messages from the printer window. We can only guess.

But what I can say is that Microsoft fixed this, and Windows XP doesn’t have the problem. When you cancel the printout, it disappears immediately from the window.

What Microsoft was faced with was the issue of implementing a cancel feature. Suppose your program is inside a great big while loop, grinding and churning, doing some particular job. In addition, you would like to offer your users an opportunity to stop the job. For this you create a window and a Cancel button. You follow the rules by adding code for the Cancel button. You’re ready to start writing the code for the Cancel button when suddenly you get stuck.

What code do you write? Your while loop is running elsewhere. How can the code for the Cancel button stop the while loop? And speaking of “running elsewhere,” does that mean you need to create a separate thread for the while loop? And then what? Do you just kill the thread? Or do you perform some complex interthread communication? Yikes! This is sounding like a mess. And this is exactly what a lot of people are up against. In fact, this is such a bizarre situation that Microsoft gave us a cancel system for one type of process, printing. When your program starts a printing process, your program can also register a dialog box that allows the user to cancel the printout. But this is specific only to printing.

Since I don’t want to show system-specific code, I’m not going to show you exact C++ code for implementing a Cancel button. Instead, I’ll offer some suggestions. First, if you’re using Windows, in which you create a callback function for each window, then these steps will work:

  1. Inside the loop performing the work, yield to the operating system every few iterations. This allows the operating system to receive more user input for your process. (In the Windows API you can use the PeekMessage function.)

  2. Have a window procedure for the Cancel button’s window that awaits the Cancel button. If your work loop yields to the system, this window procedure will get called when the user clicks the button. Then you can set a boolean variable that indicates that the Cancel button has been pressed.

  3. Back in your work loop, each time you yield to the operating system, you will then test the value of the boolean variable to see whether the Cancel button has been pressed.

If you’re using a different operating system (such as the Palm OS) where you don’t have a callback function, then you have to take a slightly different approach. Here’s one way that I’ve used in my Palm programming:

  1. Inside the loop performing the work, check for another event message in the queue.

  2. Check to see whether the Cancel button has been pressed. If so, end the loop.

In the Palm system, without a callback procedure, life is a little easier, as you can see. However, the problem here is that your work loop now has to be fundamentally aware of how to check for messages and process a Cancel button request. (And further, you’re also obligated to process other requests such as the Applications button so users can exit your program.) To many of us, that’s coupling two separate items too much, resulting in code that’s difficult to port and maintain.

Therefore, what I prefer to do is write a special function that checks the event queue for messages and then processes the events accordingly. In this function I can also check for other events such as the Applications button. But the really good thing is that now I can reuse this function in other situations. (And with Palm programming you want to do as much code reuse as possible, since you’re working with a limited amount of memory.)

REAL WORLD SCENARIO: The Cell Phone—Love It, Can’t Stand It

start example

I love my cell phone, just like most people do. And, like most people, I have a lot of problems with it. One part I use a lot is the web browser, because I can use it to check my e-mail. But the browser has a very strange way of browsing: Each web page is a menu, and you can move up or down the menu. Yet at the same time the browser has a menu across the bottom that you can choose from. The leftmost item on the bottom menu is usually the word OK. If I push the left or right arrow, I can move the highlight on the bottom menu to the left or right. If I push the up or down arrow, I can move the web page’s menu selection up or down.

But here’s the annoying part: In order to select one of the menu items on the web page, the bottom menu must have the word OK highlighted. If, for example, I’m checking my e-mail and I accidentally press the right-hand button and move to the word Folders, and I click the green button on the keypad, then I will end up in the Folders list and won’t select the item I intended to.

But that’s just the browser. Some cell phones have strange organizations for the rest of the settings. For example, one of the editors of this book pointed out that he was trying to silence his cell phone and he had a terrible time finding the silent setting. It wasn’t where he expected it to be, and he had to scroll through menu after menu until he found it. (Imagine if somebody were in a job interview, and the possible new boss was waiting on him to silence the cell phone.)

And how many times have you accidentally clicked Ignore when you meant to answer the phone? My phone has a separate OK button from the Call button. When the phone rings, if I accidentally click the OK button, I instantly ignore the call. Yet for all the other operations, I use the OK button. (The simple solution here is to make the OK button default to answer and allow me to scroll a small menu to the right, highlighting the Ignore word, and then click OK. This is better for me, since I’m more likely to answer the call than to ignore the call.)

When using the text messaging in my phone, one feature is really nice: The phone has a pretty good–sized dictionary and you can turn on a rapid entry whereby you can type just the key with the letter and then type the next key with the next letter, and the phone will start to make guesses on the word. For example, if you press the 4 key (which represents the letters g, h, and i), then the 6 key twice (which represents the letters m, n, and o), and then the 3 key (for d, e, and f), then the phone will first guess the word good. If that’s not the right word, you press the 0 key (which has the word Next printed on it), and then the word good will turn into home. Press Next again, and you’ll see gone, then hood, then hoof, and so on through several possible words. Often, the first word that comes up is the word you want, and this greatly speeds up the typing. It’s a feature I love, and although it’s a bit awkward as first, I find that I can type rather quickly.

Unfortunately, my friends who don’t like the feature have a great disadvantage: If they want to type an exclamation point, they have to press the down arrow, then the right arrow, then the OK button, then the down arrow three times (I’m not making this up!), then the OK button, and then the 8 key. That’s seven keystrokes for a rather common key for text messages among friends.

As a consumer, think about how you use products that you didn’t build. If you don’t work in the telecom field and were not involved in any of the cell phone software, then you are likely a consumer of the cell phone. Think about how you use the cell phone and how easy it is. Then apply your discoveries to your own designs.

end example

Don’t Freeze Up the Whole Computer (or the Software).

If you have a task that you need to do that might take a while, please don’t freeze up the whole computer. That’s not being a good neighbor. Some programs that deal with communication have a tendency to do this; if the software encounters a problem, the software waits for a timeout, meanwhile freezing everything up. Don’t do this. It’s bad.

If you follow the standard procedures for the operating system, then you shouldn’t have any problems. It’s when you go out of your way to hack into the system that you get into a mess. One example of this is when you bypass the operating system and directly access the hardware. I’ve heard lots of engineers complain about this, saying, “But I need direct access to the hardware.” That’s fine if they’re writing software for just them to use. But they can be sure that if such software ends up on my computer, it will be promptly deleted, and if it ends up on the computers of thousands of home users, it will result in a lot of support calls.

But along these lines is the issue of the software freezing itself. Some communications software, while friendly to the whole system, freezes up for awhile if it can’t find a dial tone while trying to use the modem.

Here’s a typical scenario: I start up the communications software, and I intend to tell it to use the local network rather than the modem. But I just returned from a business trip where I was using the modem, and I forget to switch the settings to the local network. The software tries to dial out on the modem, but I do not have a phone line hooked up. And I wait, and I wait, and I waituntil the software finally figures out that there’s no dial tone.

This has a simple solution: a Cancel command. I should be able to press Esc or choose a menu item to immediately abort and not have to wait for a timeout from the modem.

REAL WORLD SCENARIO: My Own Hourglass Problem Solved

start example

This is a completely true story (except for the obvious embellishments—but it really did happen). I have both a laptop computer and a desktop computer, and like so many other people, I was faced with the same old problem (grrrr) of how to transfer my files back and forth between the two without accidentally overwriting an older version. True, I could just use version-control software. But when I’m flying out the door with my laptop, I don’t want to have to stop and remember to go back and check in the files on the desktop before I can use them on the laptop. (Remember, when it comes to computers I’m impatient, and proud of it.)

So instead I keep my files on a CompactFlash card, the same kind of card that goes with my digital camera. I have a reader on each computer, and I just use the 64MB card just like a disk. And it works great, except for one highly annoying problem: When I would open a Microsoft Word document that’s on the card and then switch to another program and then switch back to Word, I would see the hourglass for anywhere from five to as much as 45 seconds! I would waitand waitand wait.

At first I told myself everything would be okay. I decided to just start typing and hope that the text would buffer (which it would). But little by little, my blood pressure began to rise until it reached dangerous levels.

To make a long story short, after spending hours upon hours hacking into my system, I figured out what was up: Microsoft Word maintains a working directory, and the software does some file and directory manipulation in a way that the card reader, for some reason, doesn’t allow. And when Word gets stuck on a problem, it tries again and again and again before finally giving up.

What I discovered was an incredibly simple solution: I had to make sure Word’s working directory is on the C: drive, not the CompactFlash card, which was the E: drive. I could do this by opening up a DOS window, making sure I was on the C: drive, and typing e:myfile.doc to launch a file on the E: drive.

I was incredibly proud of myself to have come up with this solution. Except, the fact is I shouldn’t have had to go through all this. Some programmers, whether it was the driver developers or the Word developers, caused this to happen. It is reminiscent of the old days of floppy drives when certain situations would cause the old DOS to first always look on the floppy drive whenever a program performed a file operation, even though a hard drive was present. The computer slowed down and was difficult to use.

Microsoft Word should know whether the working directory is a removable disk or not and, if so, not use it for some of its behind-the-scenes work. I, as the user, shouldn’t have to tell Word to always use the C: drive. But because Word has this usability problem, I was forced to stare at the hourglass much longer than I cared to.

end example

Another reason for this is that when a program is waiting on a device, the operating system may actually think the program has frozen up. Windows XP is particularly interesting with this sort of situation because (believe it or not) XP creates a temporary “ghost” window that has a white interior, the same title as your program’s window, and draws this ghost window. The user can drag this ghost window and click the close button. If the user clicks the close button, the operating system will respond with a familiar dialog box stating that the program is not responding. Then the OS may kill your program right then and there.

RULE

Don’t write your code in a way that causes the whole computer to freeze up. Instead, yield to the operating system and allow users to cancel a command.

And while on the topic of freezing up, another similar “feature” that wastes time is that of grabbing the focus from another window. The most common example I see of this little problem is the pop-up reminders in Microsoft Outlook. I use the Calendar feature in Outlook extensively, and I appreciate the little pop-up windows reminding me of my appointments. But what I don’t appreciate is that when they appear, they come all the way to the front and grab the focus. So if I’m typing this paragraph and suddenly a pop-up opens reminding me that I have to go to the dentist (ouch), and I just happen to press the Enter key, then the reminder will receive the Enter key as input and open the appointment window, taking me far away from what I was doing.

The Yahoo! Messenger program handles the pop-up situation much better: When you are talking to somebody, and you minimize the chat window, when you receive another line of text the chat window does not come to the front. However, Windows XP knows that the window changed and blinks the window’s rectangle in the start bar, effectively notifying you, all without stealing the focus.

RULE

Don’t interrupt other software by stealing the focus!




Designing Highly Useable Software
Designing Highly Useable Software
ISBN: 0782143016
EAN: 2147483647
Year: 2003
Pages: 114

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net