June, 2010

  • The Old New Thing

    2010 mid-year link clearance

    • 19 Comments

    Another round of the semi-annual link clearance.

    And, as always, the obligatory plug for my column in TechNet Magazine:

    Starting in June 2010, TechNet Magazine publishes each issue in two stages, and my column appears in the second half of the month, so don't freak out when you don't see it when a new issue first comes out.

  • The Old New Thing

    Management fallacy: If I send people email, then they will work harder

    • 15 Comments

    A project many years ago neared the conclusion of one of its project milestones. Things were getting down to the wire, and upper management was concerned that the project may not reach the milestone on schedule.

    To ensure success, they decided to send email.

    From: Senior Manager
    Subject: READ NOW!!!! More than one bug

    Please see the attached spreadsheet. If you are on the To: line you can look at the Assigned To: column and find your name.

    You are in this spreadsheet if you have 2 or more bugs assigned to you. At this stage of the project as we are winding down and entering Milestone Z, people with a high number of bugs assigned to them end up being the long poles for the release.

    We have a lot of teams getting to zero bugs, so we have people who can help you. If you need help, then ask your manager. Your manager should be on the Cc: line. It's key we get all the bugs fixed (with quality) as soon as we can. If your manager agrees you can use help, and doesn't know where to go for help, then ask me.

    Because as we all know, you can get people to work harder by sending email.

    I happened to be one of the recipients of this message, and I sent back a simple reply:

    I have more than one bug because my manager asked me to help out other people who have more than two. Thanks for your concern.

  • The Old New Thing

    The illusory repair powers of black electrical tape

    • 16 Comments

    Back in the crazy dot-com boom days, I knew someone who was into high-performance automobiles. And since these were the crazy dot-com boom days, he had the money to satisfy his urge to drive high-performance automobiles. He bought a used Ferrari, but found that it spent more time in the repair shop than on the road. To solve this problem, he bought a second Ferrari. (Note: This is not a solution available to most people.)

    One of the many trips to the auto repair shop was to address an indicator light on the dashboard which had lit up. The mechanics studied the problem and concluded that the indicator light was a false positive. There was nothing wrong with the car aside from the light itself. "Just ignore it," they told him. "We can't disconnect the light for «some reason». If it really bothers you, you can put a piece of black electrical tape over it."

    "I don't accept that solution," he replied, and told them to go and fix the problem for real.

    Some time later, he returned to pick up the car, and yes, the indicator light was off. Satisfied, he drove off.

    The next day, he took a closer look at the dashboard. The repair shop had cut out a piece of black electrical tape in the exact shape of the indicator light and placed it over the malfunctioning lamp.

  • The Old New Thing

    Redneck Scrabble: It's fun unless you had to do it for real

    • 16 Comments

    In response to my story about creative-spelling Scrabble, some people volunteered their own personal variations, like Plausible Scrabble or Rude Word Scrabble.

    One variation my friends and I sometimes play is Redneck Scrabble. All words must be spelled the way a redneck might spell it. We enjoy playing it, except for my schoolteacher friend for whom it brought back horrible memories of her training, when she was assigned to assist in teaching elementary school in a rural part of the country.

    This Web site has some other variations. I haven't played Any Language Scrabble, but one of my college friends did; they called it International Scrabble. The game was even crazier than it sounds because that particular circle of friends consisted of people who loved learning foreign languages, so pretty much anything was in play! (I don't know if anybody in the group spoke Czech, but if so, they would have totally cleaned up.)

  • The Old New Thing

    How do I get a radio button control to render its text transparently?

    • 20 Comments

    Commenter Andrei asks via the Suggestion Box for help with making the text transparent using WM_CTL­COLOR­STATIC. "Instead of the radio button now there's a black background."

    Let's look at this problem in stages. First, let's ignore the transparent part and figure out how to render text without a black background. The background color of the text comes from the color you selected into the DC when handling the WM_CTL­COLOR­STATIC message. And if you forget to set a background color, then you get whatever color is lying around in the DC, which might very well be black. Start with the scratch program and make these changes, which I'm going to write in the way I think Andrei wrote it, even though it doesn't fit the style of the rest of the scratch program.

    HBRUSH g_hbr;
    BOOL
    OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
    {
        g_hwndChild = CreateWindow(TEXT("button"), TEXT("Bingo"),
            WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
            0, 0, 0, 0, hwnd, (HMENU)1, g_hinst, 0);
        g_hbr = CreateSolidBrush(RGB(0xFF, 0x00, 0xFF)); // hot pink
        return TRUE;
    }
    
    void
    OnDestroy(HWND hwnd)
    {
        if (g_hbr) DeleteObject(g_hbr);
        PostQuitMessage(0);
    }
    
    // add to WndProc
    
      case WM_CTLCOLORSTATIC:
        if (GetDlgCtrlID(
                 GET_WM_CTLCOLOR_HWND(wParam, lParam, uiMsg)) == 1) {
          return (LRESULT)g_hbr; // override default background color
        }
        break;
    

    If you run this program, the radio button's background is indeed hot pink, well except for the text, where the color is, I dunno, it's white on my machine, but who knows what it is on yours. Since we didn't specify a color, the result is undefined. The bug here is that we handled the WM_CTL­COLOR­STATIC message incompletely. The WM_CTL­COLOR family of messages requires that the message handler do three things:

    1. Set the DC text color.
    2. Set the DC background color.
    3. Return a background brush.

    We got so excited about the background brush that we forgot the other two steps. Let's fix that.

    case WM_CTLCOLORSTATIC:
        if (GetDlgCtrlID(
                 GET_WM_CTLCOLOR_HWND(wParam, lParam, uiMsg)) == 1) {
          HDC hdc = GET_WM_CTLCOLOR_HDC(wParam, lParam, uiMsg);
          SetTextColor(hdc, RGB(0xFF, 0xFF, 0x00)); // yellow
          SetBkColor(hdc, RGB(0xFF, 0x00, 0xFF)); // hot pink
          return (LRESULT)g_hbr; // override default background color
        }
        break;
    

    (Just for fun, I chose yellow as the text color.) Now that we specified the text color and the background color, the text appears in the correct colors.

    Note that we didn't actually do anything transparently here. We just made sure that the background color we told the control to use for text matches the color we told the control to use for erasing the background. The effect looks transparent since the two colors match.

    But what if you really wanted transparency instead of fake transparency? To illustrate, let's give the control a background that is not a solid color:

    BOOL
    OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
    {
        g_hwndChild = CreateWindow(TEXT("button"), TEXT("Bingo"),
            WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
            0, 0, 0, 0, hwnd, (HMENU)1, g_hinst, 0);
        g_hbr = CreatePatternBrushFromFile(
                              TEXT("C:\\Windows\\Gone Fishing.bmp"));
        return TRUE;
    }
    

    When you run this version of the program, the radio button background consists of the Gone Fishing bitmap. (Of course, if you don't have that bitmap, then feel free to substitute another bitmap. I can't believe I had to write that.) But the text is still yellow on pink. How do we get it to be yellow on the complex background?

    By setting the background mix mode to TRANSPARENT.

    case WM_CTLCOLORSTATIC:
        if (GetDlgCtrlID(
                 GET_WM_CTLCOLOR_HWND(wParam, lParam, uiMsg)) == 1) {
          HDC hdc = GET_WM_CTLCOLOR_HDC(wParam, lParam, uiMsg);
          SetTextColor(hdc, RGB(0xFF, 0xFF, 0x00)); // yellow
          SetBkColor(hdc, RGB(0xFF, 0x00, 0xFF)); // hot pink
          SetBkMode(hdc, TRANSPARENT);
          return (LRESULT)g_hbr; // override default background color
        }
        break;
    

    According to the documentation, the background mix mode "is used with text, hatched brushes, and pen styles that are not solid lines." It's the text part we care about here. When the control does its Text­Out to draw the control text, the background mix mode causes the text to be rendered transparently.

    Exercise: There's actually one more thing you need to do, but I conveniently arranged the program so you didn't notice. What other step did I forget?

  • The Old New Thing

    6-4, 3-6, 6-7 (7-9), 7-6 (7-3), 70-68: The scoreboard doesn't even go that high

    • 16 Comments

    The match went so long that it exceeded the limits of the scoreboard! Deadspin pulls some choice quotes out of Xan Brooks's descent into madness live-blogging the marathon Wimbledon match between John Isner and Nicolas Mahut.

    Just read it. You can follow him as he loses his grip on reality before your very eyes.

    It's just a shame somebody had to lose.

  • The Old New Thing

    My life as a square (pixel)

    • 32 Comments

    The shape of the Windows screen pixel has changed over the years. It has always had a rectangular shape, but the ratio of height to width has varied. (Someday, somebody will come up with a display adapter with hexagonal or triangular pixels, and then everything will fall apart.)

    Our story begins with the Color Graphics Adapter, better known by the abbreviation CGA. Depending on the video mode, your pixels could be 1:1.2 in 320×200 color mode (all aspect ratios are given in the form width:height for some reason), or 1:2.4 in 640×200 monochrome mode. Windows used the monochrome mode because the colors available in color mode were pretty useless. You could have black, white, hot pink, and aqua; or you could have black, brown, orange-red and green (no white!). Hideous colors no matter how you slice it.

    The next major advancement in display adapter technology was the Enhanced Graphics Adapter (EGA), which brought you a stunning 16 colors in a 640×350 grid with an aspect ratio of 1.83:1. But for the step forward in terms of color, you also took a step backwards into the insanity of planar video modes. EGA memory was arranged in planes, and what's worse, each plane had the same memory address! You had to use other registers to program the video card to tell it which plane you wanted to talk to when you accessed a specific memory address. (And the memory behaved differently depending on whether you were reading from it or writing to it.)

    Next to arrive was VGA, the Video Graphics Array. (I like how the names of all the display adapters are largely meaningless.) VGA brought us square pixels, if you used them at 640×480 resolution (which is what Windows did). Finally, you had a display adapter where a stair-step pattern actually gave you a 45-degree line.

    Pretty much every display adapter since VGA has supported square pixels, and pretty much every display driver preferred those square modes instead of the non-square modes. If you go into the Windows Display control panel, you can force one of the weird non-square modes, but all of the standard dimensions (800×600, 1280×1024, etc.) use square pixels.

    Okay, so how does a program obtain the pixel aspect ratio? You start by getting a device context (or if you're really clever, an information context) for the device you are interested in, and then ask for the ASPECTX and ASPECTY device capabilities. These capabilities tell you the relative width and height of a pixel. If the x-aspect and y-aspect are equal, then you have square pixels. If not, then their ratio tells you the aspect ratio.

    As a special bonus, there is also the ASPECTXY device capability, which is the length of the diagonal of a pixel, relative to the other aspect values. This is something you can calculate yourself based on the other two metrics, but it's provided as a courtesy. Let x be the value of the ASPECTX device capability, y be the value for ASPECTY, and h be the value for ASPECTXY (h for hypotenuse). Then the values are related by the formula

    h² = x² + y²

    (Of course, there will be rounding errors since all the device capabilities are integers.)

    Now that non-square pixels have been pretty much entirely replaced by square pixels in the past fifteen years, I wonder how many programs will start looking weird once a display with non-square pixels is reintroduced to the world of Windows. With newer and more unusual form factors for PCs coming out all the time, it's perhaps just a matter of time before a non-square-pixel display becomes the new must-have device. (And that time appears to have come: Pixels on HD TVs are not always square.)

    The reality of non-square pixels explains why most metrics come in both horizontal and vertical versions.

  • The Old New Thing

    When setting expectations, you also have to deny them when necessary

    • 24 Comments

    Occasionally the shell team will get a request from a customer via their customer liaison that requests information on how to accomplish something or other, and before we'll answer the question, we want to know what the support boundaries are. For example, we might provide a mechanism that works on Windows Vista but comes with no guarantees that it'll work in the future. (This sort of one-off solution might be appropriate for, say, a corporate deployment, where the company controls all the computers in their organization and therefore controls what version of Windows runs on each of them.) The customer liaison responds:

    Thanks for the information. I do not plan on giving them any expectations on what to expect in Windows 7. Is this okay?

    It's not enough not to give any expectations. You must deny expectations explicitly. If you say nothing, then the customer will assume that the solution will continue to work in the future.

    Of course, even explicitly denying support in future versions might not be enough. I remember one review of Windows Vista that said that one of its serious flaws was that the Windows XP PowerToys didn't run on it. Even though the Windows XP PowerToys explicitly state right at the top, "PowerToys are for Windows XP only and will not work with Windows Vista."

    Sometimes the customer fails to realize what it means to rely on behavior that is explicitly not supported in future versions of Windows. I recall more than once, a customer asked for a way to accomplish something, and we provided a mechanism with the explicit warning that it is not guaranteed to work on future versions of Windows. The customer replied, "We understand that this technique may not work on future versions of Windows."

    I got the impression that customer was not a corporation preparing a Windows deployment but was rather a software vendor developing retail software. I asked a clarifying question: "Do your customers understand that this technique may not work on future versions of Windows? Are you going to inform them before installation that the program intentionally relies on behavior which may not work on future versions of Windows? (That way, they can assess whether they wish to purchase your program.) And are you prepared to support your customers when they upgrade to the next version of Windows and your program stops working?"

    This was, apparently, a level of understanding that they had not fully-incorporated. Upon realizing that they were making a decision on behalf of their customers, they decided that perhaps their customers wouldn't be happy with that decision they were about to make.

  • The Old New Thing

    The best way to prove somebody incompetent is to make up stuff and then point out that it's idiotic

    • 51 Comments

    One way to show that somebody is incompetent is to tell them that something they're doing is stupid, even when it's not what they're doing. Take for example this comment saying that it's stupid for copy and paste to use data objects which can allow code to execute. Um, we were talking about drag and drop, not copy and paste. And in fact, the copy and paste functionality of console windows hasn't changed. You can still copy and paste with impunity.

    Second example: "And yet, the feature I really want is never implemented: Rearranging the taskbar." Except it isn't true. Windows 7 implemented it.

    Third example: "Or we could sideline the cmd.exe stuff and restart with a bash style interpreter." I thought we did that and called it PowerShell.

    Fourth example: "If the OS had its own thread and stack for displaying application errors which worked for _any_ application error (stack overflow included), then nobody would have to even think about writing such hacks." Windows Vista already implemented your suggestion.

    Fifth example: "There should be an API which will hide the registry accesses. I'm talking about things like registering a file extension." Oh, you mean the Default Programs API?

    Actually, my examples sort of morphed into people asking for features which already exist. Oh well, I guess it wasn't a very good rant, then.

  • The Old New Thing

    How do I customize the Favorite Links section of the File Open dialog?

    • 12 Comments

    In the standard File Open dialog in Windows Vista and Windows 7, the top of the navigation bar contains a section called Favorite Links (on Windows Vista) or just Favorites (on Windows 7). These items also appear in the Explorer window's Navigation Pane. How do I customize those links?

    You add or remove them from your Links folder.

    To open your Links folder on Windows Vista, open the Start menu and click on your name. This opens an Explorer window to view your user profile. Double-click the folder called Links. On Windows; 7, it's much easier: Right-click the word Favorites and select Open in new window. Anyway, once you get the folder open one way or another, you can edit the list. To remove an item from the list, just delete it from the folder. To add a folder to the list, drag it in. (The default action for the Links folder is Create Shortcut.)

    Note that only shortcuts to folders will work here, or more specifically, shortcuts to containers, because when you click on an item, the File Open dialog needs to show you the contents of the item you selected.

Page 1 of 4 (32 items) 1234