August, 2008

  • The Old New Thing

    For that, you'll have to call security

    • 22 Comments

    Yahoo! is notorious for bad parking, but they're not the only ones.

    Microsoft has recurring parking problems as well, caused by office space shortages that force employees to be crammed into offices at double or even triple the intended density. Since parking lots are sized based on the expected number of cars, overstuffing a building with employees also results in an overstuffed parking lot. That's one of the reasons I ride my bicycle to work: There's always a place to park your bicycle.¹

    Occasionally, however, I do drive, and then I find myself hunting for parking like everybody else. One day I thought I spotted a space, only to find that a pick-up truck had decided to take up two spaces. I began to take pictures so I could file a report, when a white SUV drove past, a white SUV with Security written on it.

    I caught the attention of the driver and pointed out the problem.

    "Hi, this truck is parked in two spaces, and it doesn't have a parking permit either. Can you do anything about it?"

    The driver replied, "You'll have to call security."

    I was so not expecting that.

    I was left speechless for a moment, then managed to reply, "You're security."

    Footnotes

    ¹Actually, that wasn't true ten years ago. Back then, the bike racks were full of bicycles that never moved, because a bicycle that never moves never loses its parking spot. Thankfully, the Real Estate and Facilities folks (known to insiders as RE&F) have since instituted an annual "abandoned bicycle sweep" that ensures that the bike racks are used by people who actually ride their bicycles.

  • The Old New Thing

    The caret serves as the continuation character for batch files

    • 12 Comments

    We saw earlier that the caret is the escape character for the batch language. In a comment to that article, KJK::Hyperion mentioned that the caret serves as the line continuation character. A useful tip if you still find yourself messing with batch files. Mark Yocum elaborates on this point a bit more.

  • The Old New Thing

    What's with this MSH_MOUSEWHEEL message?

    • 34 Comments

    The hardware folks had this mouse wheel thing they were making, and they needed a way to get applications to support the mouse. Now, one way of doing this was to say, "Well, we'll start selling this wheel mouse, but no applications can use it until the next version of Windows is released, one that supports the wheel." Of course, that would have meant waiting until Windows NT 4 came out, and who know when that would be. Plus it meant that people would have to upgrade Windows in order to take advantage of their fancy new mouse. As you can imagine, they weren't too pleased with the "wait a few years" plan.

    In the interim, they proposed a stopgap mechanism for applications to respond to the mouse wheel. Enter the zmouse.h header file and its MSH_MOUSEWHEEL registered message. When you installed the wheel mouse driver, it listened for wheel events from the hardware and posted this new message when the mouse wheel turned, and applications could just respond to either the WM_MOUSEWHEEL message (if running on a version of Windows that supported the message) or the MSH_MOUSEWHEEL message (if running on an older version of Windows that didn't). Unfortunately, the two messages behave differently, so it's not a simple matter of writing

    if (uMsg == WM_MOUSEWHEEL || uMsg == g_msgWheel) {
     ... do wheel stuff ...
    }
    

    (These next few paragraphs summarize what is already spelled out in MSDN; you can skip them if you already know how the messages work.)

    First, let's look at WM_MOUSEWHEEL. This message is delivered to the window that has focus (in the SetFocus sense). If the window procedure doesn't handle the message and just passes it through to the DefWindowProc function, then the DefWindowProc function forward the message to the window's parent. In this way, the WM_MOUSEWHEEL message automatically "bubbles outward" from the focus window up the parent chain until somebody finally handles the message (or it goes all the way to the top without being handled at all).

    On the other hand, the MSH_MOUSEWHEEL message works from the outside in. It is delivered to the foreground window (in the SetForegroundWindow sense). If the window procedure doesn't want to handle the message, it can forward the message to child windows of its choice, until one of them returns TRUE to indicate that the message was handled, or until no further candidates exist.

    I'll summarize these differences in a table, since people seem to like tables so much.

    WM_MOUSEWHEEL MSH_MOUSEWHEEL
    Propagation direction Inside-out Outside-in
    Propagation mechanism DefWindowProc SendMessage
    Handling Automatic Manual: Application checks return value
    from child to determine what to do next
    Return value if processed Zero TRUE
    Return value if not processed DefWindowProc FALSE

    Notice that WM_MOUSEWHEEL is much simpler, and the inside-out propagation mechanism retains the spirit of other messages such as WM_CONTEXTMENU and WM_SETCURSOR. Why can't MSH_MOUSEWHEEL do it the same way?

    Well, first of all, MSH_MOUSEWHEEL doesn't have the luxury of being able to modify the DefWindowProc function. After all, that's the whole point of introducing the message in the first place, because we're trying to add wheel support to an older operating system that predated mouse wheels. Put in other words, if we could modify DefWindowProc to handle the MSH_MOUSEWHEEL message, then we wouldn't have needed the MSH_MOUSEWHEEL message to begin with; we would've just modified DefWindowProc to handle the WM_MOUSEWHEEL message.

    The argument in the previous paragraph is a frustratingly common one. Given a problem X and a workaround Y, somebody will ask, "Why didn't you use method Z?" If you look at method Z, though, you'll see that it suffers from the exact same problem X.

    Here's a real-world example of the "confused workaround":

    "Since the I-90 bridge is closed, I can't take the 550 bus to get from Bellevue to Safeco Field. Instead, I'm going to take the 230 to Redmond, and then change to the 545."

    — Well, that's silly. Why not take the 245 to Eastgate, and then change to the 554? It's a lot faster.

    "Um, the 554 uses the I-90 bridge, too."

    Okay, so you can't change DefWindowProc, but why not at least propagate the MSH_MOUSEWHEEL from the inside out instead of from the outside in?

    Starting with the focus window assumes you can even find out what the focus window is, but if you had paid attention to the Five Things Every Win32 Programmer Should Know, you would have known that each thread has its own focus window. (Not nitpickily true, but true enough.) Consequently, when the helper program that injects MSH_MOUSEWHEEL messages calls GetFocus, it just gets its own focus window, not the focus window of the thread that controls the foreground window. (Remember, we're talking 1996, long before the GetGUIThreadInfo function was invented. History buffs can find out more from Meet The Inventor of the Mouse Wheel.) Since inside-out was off the table, that pretty much forced outside-in.

    Now that you know how mouse wheel messages work, you can explain the behavior this customer is seeing:

    I'm seeing the WM_MOUSEWHEEL message being delivered to the wrong child window. I have a parent window with two children. Even though I move the mouse pointer over child 1, the WM_MOUSEWHEEL goes to child 2.
  • The Old New Thing

    AOL is moving closer to jettisoning dial-up, except for one person

    • 10 Comments

    When I read this story that AOL is ready to spin off their dial-up service, I wondered if they will remember to give the new dial-up number to the winner of that contest.

  • The Old New Thing

    Microspeak: The long pole

    • 23 Comments

    The long pole is the part of the project that is on the critical path due to its length. For example, if you have a project that consists of three independent sub-projects, then the sub-project with the longest completion date is the long pole.

    The etymology of this term is simultaneously obvious yet hard to pin down. Intuitively, the long pole is the one that determines the height: If you have a tent supported by three poles, then the long pole decides how tall the tent is. If you have a collection of poles you want to put in the back of a pick-up truck, the long pole is the one that decides how big a bed you need. If you have a set of poles and you hold them in your hand in a sheaf and rest the bottoms on the ground, then the long pole is the one that sticks up the highest.

    It is my impression that the tent analogy is the one that provides the source for this bit of Microspeak, but I'm not absolutely sure. If true, it's a nice bit of double-wordplay, because not only is it an analogy, but it's also a pun: The long pole is the one holding everything up.

    You don't want to be a long pole in your project, because that just means that everybody will be giving your component extra scrutiny to make sure it's not going to make everything late.

    Here are some citations.

    Design on track, but setup work appears to be long pole.
    XYZ work is long pole in the schedule; not clear whether issue can be mitigated.
    XYZ is still the long pole, now out [i.e., over schedule] by about six days, down from eight days last week after the ABC work was offloaded to UVW.
  • The Old New Thing

    Why, when you sort by name, doesn't it actually sort by name?

    • 25 Comments

    When you right-click on the desktop or in an Explorer window and select "Sort by... Name", why doesn't it actually sort by name?

    Because "Sort according to the default sort order for the column whose title is... Name" is too long.

    The default sort order for the first column (whose name is "Name") is to sort by name, mostly. The actual sort order for the desktop and file folders (note: implementation detail, subject to change at any time) is really a two-tiered sort. First, the items are sorted into buckets; the first bucket contains the virtual folders, the second bucket contains file folders (directories), and the third bucket contains regular files. Sorting within the first bucket is done by the "item order"; sorting within the second and third buckets is by name. (And it's not by ASCII code any more. There's also special treatment for numbers and periods.)

    The "item order" (a term I just made up) for My Computer, My Documents, and Recycle Bin were specifically chosen in Windows 95 so that the icons on the desktop appeared in that order. I believe it was in Windows 2000 that the order was changed to My Documents, My Computer, Recycle Bin in order to put the focus on document management.

    (And those who have read Appendix A of my book will know what sort of application compatibility problems arose from that simple change.)

  • The Old New Thing

    I warned you: The dangers of attaching input queues

    • 53 Comments

    Some people didn't take to heart my cautions on the subject of attached input queues, item number five on the list of five things every Win32 programmer should know. And then they find that their application stops responding.

    // Code in italics is wrong
    void TryToStealFocus(HWND hwnd)
    {
      // First try plain SetForegroundWindow
      SetForegroundWindow(hwnd);
      HWND hwndFG = GetForegroundWindow();
      if (hwndFG == hwnd) return;
    
      // That didn't work - if the foreground window belongs
      // to another thread, attach to that thread and try again
      DWORD dwCurrentThread = GetCurrentThreadId();
      DWORD dwFGThread = GetWindowThreadProcessId(hwndFG, NULL);
      if (dwFGThread == dwCurrentThread) return;
    
      AttachThreadInput(dwCurrentThread, dwFGThread, TRUE);
      SetForegroundWindow(hwnd); // hangs here
      AttachThreadInput(dwCurrentThread, dwFGThread, FALSE);
    }
    

    Their customer feedback data shows that this function often hangs at the second call to SetForegroundWindow. My exercise for you is to explain why. (Here's someone else with the same problem.)

    (Note that both of these customers are trying to circumvent the foreground lock timeout so that they can steal focus and shove a dialog box in the user's face.)

Page 4 of 4 (37 items) 1234