August, 2008

  • The Old New Thing

    Destroying the module and resource information associated with an icon

    • 0 Comments

    We've seen that icons and cursors know where they came from, and the window manager uses this information when you ask it to change the size of an icon. But not all icons carry this information, only icons created by passing a HINSTANCE and a resource name.

    You can use this to your advantage if you want to destroy the module and resource information associated with an icon. For example, the CreateIconIndirect function creates an icon from raw bitmap information without reference to an HINSTANCE or a resource name. This allows you to create icons at runtime, but it also allows you to create an icon that "throws away" the bonus information.

    HICON CopyIconWithoutResourceInfo(HICON hicoSrc)
    {
      ICONINFO ii;
      HICON hico = NULL;
      if (GetIconInfo(hicoSrc, &ii)) {
        hico = CreateIconIndirect(&ii);
        if (ii.hbmMask) DeleteObject(ii.hbmMask);
        if (ii.hbmColor) DeleteObject(ii.hbmColor);
      }
      return hico;
    }
    

    Now, throwing away this information is a desperation move, because it prevents the window manager from using the original resource information when resizing an icon, resulting in ugly stretched icons.

    You might even be throwing this information away by mistake. For example, if your program is asked to produce an icon, it's best if you load the icon with a function like LoadImage because that records the bonus information; if the caller decides to resize the icon, it can do so with the CopyImage function while retaining full fidelity. On the other hand, if you use a function like ExtractIcon or CreateIconFromResource, that will not have the bonus information, and any icon stretching that takes place will end up looking pretty ugly.

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    Oh no, there's fog in San Francisco!

    • 10 Comments

    My flight out of Seattle on Wednesday was delayed for about an hour. The explanation: Fog in San Francisco.

    Whoa, fog in San Francisco. Must've taken them by surprise!

  • The Old New Thing

    Why does Explorer generate a page fault every two seconds?

    • 31 Comments

    If you fire up Task Manager and look at the page fault count, you'll see that even when nothing is going on, Explorer takes a page fault every two seconds. Isn't this bad? I though you weren't supposed to poll.

    Here's an interesting experiment: Change your update speed to High. Wow, the page fault rate quadruples to a page fault every half second. At this point, you should start suspecting some sort of Heisenbehavior, that is, that the behavior of the system is changing due to your act of observing it.

    The page faults are coming from the CPU meter in the notification area. At each update, Task Manager sets a new icon into the notification area, and Explorer resizes it from the default icon size (which is the size of the icon that Task Manager hands it) to the notification icon size. To obtain the best quality image, the taskbar uses the LR_COPYFROMRESOURCE flag. This means that the window manager goes back to taskmgr.exe to locate the best match, which in turn triggers a soft page fault. It's a soft page fault since the information is already in the cache (after all, we access it every two seconds!), so no actual disk access occurs. But it still shows up as a page fault, and that makes some people nervous.

    What could Task Manager do to avoid triggering this false alarm and freaking people out? Well, when it calls Shell_NotifyIcon, it could pass icons that were loaded at the size GetSystemMetrics(SM_CXSMICON) by GetSystemMetrics(SM_CYSMICON). That way, when the notification area makes a copy of the icon, it won't need to be resized since it's already at the correct size.

    Now, there's really nothing wrong with the soft page faults aside from all the time the shell team has to spend explaining to people that nothing is actually wrong. Next time, we'll look at the wrong way of avoiding the soft page faults. Even though it's the wrong way, the exercise is still instructive.

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    When somebody says a game is like chess, it is usually completely unlike chess

    • 36 Comments

    Chess has become elevated to the gold standard of board games. Everybody wishes their game had the cultural gravity of chess, a game whose mere mention elevates you to the category of deep thinker and profound strategist. (We'll set aside the scrawny glasses-wearing nerd part for now.)

    I've learned that when somebody says a game is like chess, it's pretty much guaranteed that the game in fact bears no resemblance to chess whatsoever.

    I came to this realization when somebody pulled out a game with a strange-looking board with what looked like plastic volcanoes glued to the surface, catwalks, and a lazy susan. Each player was represented by a token, set in its respective starting position. I asked, "Hey, what's this game?"

    The person replied, "It's a lot like chess. First you roll the dice..."

    (Translation from the German in that link above, for those who need some help.)

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    Icons and cursors know where they came from

    • 18 Comments

    If you create an icon by calling LoadIcon, the window manager loads the specified icon from the module you specified, but it also remembers where the icon came from. (This discussion also applies, mutatis mutandis to cursors, but I will just talk about icons to avoid awkardness.) When you pass the LR_COPYFROMRESOURCE flag to the CopyImage function, the window manager goes back to the original icon source to create the copy you requested rather than blindly stretching the pixels of the icon you passed in.

    Remember that an ICO file represents not just one icon but rather a collection of icons (known as an "icon group"), each at a different size or color depth. The intent is that each icon in the icon group depicts the same underlying image, just tuned for particular settings. (Now, mind you, there is no enforcement of this intent. If you make your 16×16 image a smiling-face and your 32×32 image a barking dog, well, then that's your problem.) For example, a single ICO file might contain a 16×16 image, a 32×32 image, and a 48×48 image. If somebody asks for the icon at one of those sizes, then the corresponding image is used. On the other hand, if somebody asks for, say, the 24×24 image, the window manager will take the 32×32 image and stretch it to the necessary size.

    You can recover this "hidden source information" with the GetIconInfoEx function (new for Windows Vista). If the icon was loaded by ordinal, then the szResName is an empty string and the ordinal is placed in the wResID member. If the icon was loaded by name, then wResID is zero and szResName contains the resource name.

    This is just some background information about icons (and cursors). Next time, we'll put this information to use to solve a problem.

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    It's not Christmas: Nobody enjoys unwrapping your present

    • 142 Comments

    I don't know why it happens, but it happens with disturbing frequency. A customer wants to report a problem, and then illustrate it with a screenshot or two, but instead of attaching the screenshots, they paste the screenshots inside a Word document (and for some reason it's always Word) and then attach the Word document.

    It's not a Christmas present. People aren't going to say "Wow, I wonder what's inside? I'm brimming with anticipation!" They're going to say, "Oh great, I can't even see the screen shot. I have to download the attachment, scan it for viruses, then load it into Word. Oh wait, this is a Word 2007 document and I only have Word 2003; let me run the converter first. Okay good, now I can open the document to see, oh, look, it's a picture." Most people won't bother. And then you're going to wonder why nobody answered your first message.

    If you insist on attaching the pictures, just attach them directly. And use a compressed image format like JPG or PNG, please. Don't send uncompressed screenshots; they are ridiculously huge. Cropping the image to the relevant portion of the screen helps, too. (This is very easy to do with the Snipping Tool.)

    In March of this year, a customer wrote, "I have attached a Word document that describes the problem." (Hey, here's an idea: Why not describe the problem in your email message?)

    The Word document contained a screenshot.

    The screenshot was of an email message.

    The email message contained a screenshot.

    Bonus remark from the customer liaison: "Once you open the document, you may need to zoom it further to read it."

    Wooden table not included.

  • The Old New Thing

    As a courtesy to performers and other audience members, please turn off blinking head-mounted devices

    • 22 Comments

    When a theater or concert performance begins, there is often an announcement asking audience members to silence their cell phones and similar devices. Some time ago, a light blinked near the ear of a gentleman a few rows in front of me throughout the entire performance. I couldn't tell what it was for sure, but it appeared to be the indicator light of a Bluetooth headset.

    Blink.

    Five seconds later:

    Blink.

    Five seconds later:

    Blink.

    Repeat for two hours.

    What I want to know is, was this guy expecting a call during the show? If his phone rang, would he answer it from his seat?

    (Added: This was before Bluetooth headsets were in common use. It wasn't until after the show that I was able to guess what it was.)

  • The Old New Thing

    What happened to the Search option on the right hand side of the Start menu?

    • 21 Comments

    You may have noticed that in Windows Vista Service Pack 1, the Search option on the right hand side of the Start menu has been removed. What happened to it?

    It's redundant with the Search Box, that thing that has the keyboard focus when you initially open the Start menu. (But if you really want to open Explorer in Search mode, you can still type Windows+F or press F3 when focus is on the Start menu.) And if you want to plug into the search protocol that the Start menu uses, this MSDN page provides a sample registration and describes what sorts of queries you will be handed by the shell.

  • The Old New Thing

    The Seattle Danskin Women's Triathlon 2008

    • 10 Comments

    This Sunday will be the Nth annual Seattle Danskin Women's Triathlon (for some value of N greater than 1), the largest women-only triathlon. I learned about this event last year when I saw that the express lanes on the I-90 bridge were crowded with bicyclists, and I went online to try to figure out what was going on.

    As I clicked around, I found the Volunteer Site and was particularly impressed with the Swim Angels. (More details.) These are strong women swimmers whose job it is to accompany the weaker swimmers and provide moral support.

    I was chatting with a friend of mine, who noted that one of the first volunteer positions to fill is the "Help the women change out of their wetsuits in the transition area." Go figure.

    Best wishes to all of this weekend's participants!

  • The Old New Thing

    The implementation of iterators in C# and its consequences (part 4)

    • 28 Comments

    You can breathe a sigh of relief. Our long national nightmare is over: this is the end of CLR Week 2008. We wind down with a look back at iterators.

    Michael Entin points out that you can use C# iterators to make asynchronous code easier to write. You can use C# iterators for more than simply iterating.

    The automatic conversion of straight line code into a state machine is handy when you want an easy way to write, well, a state machine. It's one of those things that's blindingly obvious once you look at it the right way.

    The transformation that the yield return statement induces on your function turns it from a boring function into an implicit state machine: When you execute a yield return, execution of your function is suspended until somebody asks your iterator the next item, at which point execution resumes at the statement after the yield return. This is exactly what you want when breaking a synchronous function into asynchronous pieces: Each time you would normally block on an operation, you instead perform a yield return, and when the operation completes, you call the MoveNext method, which resumes execution of the function until the next time it needs to wait for something and performs a yield return.

    It's so simple it's magic.

    Additional iterator-related reading:

Page 2 of 4 (37 items) 1234