• The Old New Thing

    The company picnic, sponsored by Microsoft


    Robert Scoble blogs from the Microsoft company picnic. Although he writes, "Microsoft holds a picnic for its employees every year," this suggests that the picnic is organized by Microsoft. It isn't.

    The company picnic is run by a professional company picnic company. They also do the Alaska Airlines company picnic, and probably those of many other organizations who don't put their picnic information on the public Internet. Wander down to Mountain Meadows Farm any weekend during the summer and you're likely to see a picnic or other group event under way.

  • The Old New Thing

    What is the DS_CONTROL style for?


    The DS_CONTROL dialog box style indicates that the dialog being created is being used as the child of another dialog rather than being a top-level dialog in and of itself.

    Nested dialogs are hardly a scary sight. You see them in property sheets, for example. Each page on a property sheet is a separate dialog; they all live inside the outer dialog, the property sheet itself. Nested dialogs are sometimes used in the common file dialogs: You can see one in action if you do a Save As from Notepad. The extra options at the bottom come from a nested dialog.

    When you set the DS_CONTROL style on a dialog template (or set the WS_EX_CONTROLPARENT extended style on a regular window), a bunch of new rules kick in.

    First of all, the WS_CAPTION and WS_SYSMENU styles in your dialog template are ignored. Because you're a child window now, not a top-level window, so you don't get a caption bar or a system menu. (The caption bar and system menu come from the outer window.)

    Next, the dialog navigation functions like GetNextDlgTabItem will recurse into windows marked WS_EX_CONTROLPARENT when they inspect the controls on a dialog box (in GetNextDlgTabItem's case, because it is looking for a control to tab to). Without the extended style, the control search treats the embedded dialog box as one giant control rather than as a container for other controls.

    When you create a dialog with the DS_CONTROL style, you invariably use one of the creation functions like CreateDialogParam rather than one of the dialog box functions like DialogBoxParam, because the modal loop is controlled by the outer dialog, not the inner one.

    The recursive behavior is important to know in order to avoid sending the dialog manager into an infinite loop. When you ask GetNextDlgTabItem to look for the previous item, what it does is take the starting control, then walk through the controls on the dialog until it comes back to the starting point, at which point it returns the one it saw before that one. If you forget to mark your dialog as DS_CONTROL, and focus started out in the sub-dialog, then the control enumeration will not recurse into the sub-dialog and consequently the starting point will never be found. The dialog manager will just keep looping, hunting for that starting-point control and never finding it.

    (This problem exists even without DS_CONTROL. If you start out on a disabled or invisible control, then the walk through the controls will again never find the starting point, since disabled and invisible controls are skipped over when tabbing through a dialog.)

  • The Old New Thing

    When should you use a sunken client area?


    The WS_EX_CLIENTEDGE extended window style allows you to create a window whose client area is "sunken". When should you use this style?

    The Guidelines for User Interface Developers and Designers says in the section on the Design of Visual Elements that the sunken border should be used "to define the work area within a window".

    Specifically what this means is that a sunken client area indicates that the window is a "container". So, for example, the Explorer contents pane gets a sunken client area since a folder "contains" its elements. Users expect to be able to manipulate the items inside a container. By contrast, a dialog box is not a container, so it doesn't get a sunken client area.

    At least those were the rules back in 1995. Perhaps the rules have changed since then. (Indeed I wouldn't be surprised if they have.)

  • The Old New Thing

    The evolution of mascara in Windows UI


    The "look" of the Windows user interface has gone through fashion cycles.

    In the beginning, there was Windows 1.0, which looked very flat because screen resolutions were rather low in those days and color depth was practically nonexistent. If you had 16 colors, you were doing pretty good. You couldn't afford to spend very many pixels on fluff like borders, and shadows were out of the question due to lack of color depth.

    The "flat look" continued in Windows 2.0, but Windows 3.0 added a hint of 3D (notice the beveling in the minimize/maximize buttons and in the toolbar buttons on the help window).

    Other people decided that the 3D look was the hot new thing, and libraries sprung up to add 3D shadow and outlining effects to nearly everything. The library CTL3D.DLL started out as just an Excel thing, but it grew in popularity until it became the "standard" way to make your dialog boxes "even more 3D".

    Come Windows 95, even more of the system had a 3D look. Notice the beveling along the inside edge of the panes in the Explorer window. Furthermore, 3D-ness was turned on by default for all programs that marked themselves as "4.0"; i.e., programs that were designed for Windows 95. For programs that wanted to run on older versions of Windows as well, a new dialog style DS_3DLOOK was added, so that they could indicate that they wanted 3D-ization if available.

    And if the 3D provided by Windows 95 by default wasn't enough, you could use CTL3D32.DLL to make your controls even more 3D. By this point, things started getting really ugly. Buttons on dialog boxes had so many heavy black outlines that it started to look like a really bad mascara job.

    Fortunately, like many fashions that get out of hand, people realized that too much 3D is not a good thing. User interfaces got flatter. Instead of using 3D effects and bold outlines to separate items, subtler dividers were used. Divider lines became more subdued and sometimes disappeared entirely.

    Microsoft Office and Microsoft Money were two programs that embraced the "less is more" approach. In this screenshot from Microsoft Money, observe that the beveling is gone. There are no 3D effects. Buttons are flat and unobtrusive. The task pane separates itself from the content pane by a simple gray line and a change in background shade. Even the toolbar has gone flat. Office 2000 also went largely flat, though some 3D effects linger, in the grooves and in the scrollbars (not visible in picture).

    Windows XP jumped on the "flat is good" bandwagon and even got rid of the separator line between the tasks pane and the contents pane. The division is merely implied by the change in color. "Separation through juxtaposition."

    Office XP and Outlook 2003 continue the trend and flatten nearly everything aside from the scrollbar elements. Blocks of color are used to separate elements onscreen, sometimes with the help of simple outlines.

    So now the pendulum of fashion has swung away from 3D back towards flatness. Who knows how long this school of visual expression will hold the upper hand. Will 3D return with a vengeance when people tire of the starkness of the flat look?

  • The Old New Thing

    Disabling the program crash dialog


    If you don't want your program to display the standard crash dialog, you can disable it by setting the SEM_NOGPFAULTERRORBOX flag in the process error mode.

    The simple-minded way is just to do


    but this overwrites the previous error mode rather than augmenting it. In other words, you inadvertently turned off the other error modes!

    Unfortunately, there is no GetErrorMode function, so you have to do a double-shuffle.

    SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);

    This sets the new error mode (possibly disabling some other error modes that had been set) and saves the previous mode. Then it sets the error mode the right way, adding the SEM_NOGPFAULTERRORBOX flag to the existing error modes.

    Merging with existing error modes is important. For example, the previous error mode may have included SEM_NOALIGNMENTFAULTEXCEPT. If you casually turned that off, then the program would not longer receive automatic alignment fault fixups and will start crashing.

    (But if you read the documentation, you'll see that SEM_NOALIGNMENTFAULTEXCEPT is special: The system won't let you turn it off once it's been turned on. Why? Because too many people were already making this mistake. I remember before this special rule was introduced. Programs were crashing left and right because they didn't do the double-set shuffle above; as a result, they started crashing on alignment faults. So the special rule had to be added. Welcome to the world of compatibility, where it is the operating system's duty to cover for other people's mistakes. Mind you, the design of the SetErrorMode function makes this mistake a very easy one to commit.)

    Note that the error mode is a process-wide setting, not a per-thread setting. This means that manipulating the process error mode is not something you should do lightly, since it may have unintended consequences for other threads (which you might not have control over). For safety's sake, a program should set its error mode when it starts up and not mess with it thereafter.

    Of course, if you disable the crash dialog, then you also miss out on the opportunity to retrieve crash reports collected by Windows Error Reporting so you can see where your program is crashing in the real world.

  • The Old New Thing

    Norway, drunk on success, becomes a country of layabouts


    Norwegians have it so good that they've started getting lazy:

    Before the oil boom, when Norway was mostly poor and largely isolated, the country survived on its hard work and self-reliance, two stalwart Scandinavian virtues.

    Now, with the country still bulging from three decades of oil money, Norway is discovering that sudden wealth does not come without complications: The country's bedrock work ethic is caving in.

    On a similar note, here's an essay on Norwegian 'fellesferie'—vacation time—and its impact on getting anything done at all during the summer.

  • The Old New Thing

    A twenty-foot-long computer


    Back in the days of Windows 95, when Plug and Play was in its infancy, one of the things the Plug and Play team did was push the PCI specification to an absurd extreme.

    They took a computer and put it at one end of a hallway. They then built a chain of PCI bridge cards that ran down the hallway, and at the end of the chain, plugged in a video card.

    And then they turned it on.

    Amazingly, it actually worked. The machine booted and used a video card twenty feet away. (I'm guessing at the distance. It was a long time ago.) It took two people to operate this computer, one to move the mouse and type, and another to watch the monitor at the other end and report where the pointer was and what was happening on the screen.

    And the latency was insane.

    But it did work and thereby validated the original design.

    Other Plug and Play trivia: The phrase "Plug and Play" had already been trademarked at the time, and Microsoft had to obtain the rights to the phrase from the original owners.

  • The Old New Thing

    Slightly closer to a proper football (i.e., soccer) match


    This weekend, I attended a soccer match between Chelsea FC and Celtic FC at Seahawks Stadium Qwest Field. The game was the opener of the 2004 ChampionsWorld Series, wherein some of the top soccer teams from Europe tour North America to give us yanks a chance to see how football is done for real.

    From reading the team's web sites before the match, you'd think that Chelsea had already thrown in the towel, because even before the game started, they were making excuses, blaming jet lag for their loss. The excuses weren't necessary, though, because Chelsea dominated the match and ultimately won 4–2.

    It was interesting comparing the two teams' styles. When Chelsea scored a goal, you could watch it develop. A through ball, a man open, a pass or two, and the ball is in the back of the net. Celtic's goals were more of a "And he's got the ball, and... hey, how'd he score?" It all happened so fast it was over before it began.

    Attendance was 30,000, only half the capacity of Seahawks Stadium Qwest Field, but a decent turnout I think for a sport that is still considered fringe here in the States.

    Here's Raymond's checklist comparing the match to what he figures a "proper" British football match to be like.

    A Proper
    Segregated cheering sections
    "Neutral" cheering section ?
    Post-game riot  
    Alcohol sold during match  
    Police officers around pitch 
    Streaker interrupts match

    One aspect of the British football divisions that I find fascinating is relegation, wherein the worst teams of the year are demoted to the next lower league, replaced by the top teams of that next lower league. This doesn't happen in U.S. sports leagues (at least not any of the major ones). In fact, in U.S. sports leagues, the team that has the worst record is rewarded with an early draft pick! How's that for reverse incentive.

  • The Old New Thing

    Why do some process stay in Task Manager after they've been killed?


    When a process ends (either of natural causes or due to something harsher like TerminateProcess), the user-mode part of the process is thrown away. But the kernel-mode part can't go away until all drivers are finished with the thread, too.

    For example, if a thread was in the middle of an I/O operation, the kernel signals to the driver responsible for the I/O that the operation should be cancelled. If the driver is well-behaved, it cleans up the bookkeeping for the incomplete I/O and releases the thread.

    If the driver is not as well-behaved (or if the hardware that the driver is managing is acting up), it may take a long time for it to clean up the incomplete I/O. During that time, the driver holds that thread (and therefore the process that the thread belongs to) hostage.

    (This is a simplification of what actually goes on. Commenter Skywing gave a more precise explanation, for those who like more precise explanations.)

    If you think your problem is a wedged driver, you can drop into the kernel debugger, find the process that is stuck and look at its threads to see why they aren't exiting. You can use the !irp debugger command to view any pending IRPs to see what device is not completing.

    After all the drivers have acknowledged the death of the process, the "meat" of the process finally goes away. All that remains is the "process object", which lingers until all handles to the process and all the threads in the process have been closed. (You did remember to CloseHandle the handles returned in the PROCESS_INFORMATION structure that you passed to the CreateProcess function, didn't you?)

    In other words, if a process hangs around after you've terminated it, it's really dead, but its remnants will remain in the system until all drivers have cleaned up their process bookkeeping, and all open handles to the process have been closed.

  • The Old New Thing

    Why can't you trap TerminateProcess?


    If a user fires up Task Manager and clicks "End Task" on your program, Windows first tries to shut down your program nicely, by sending WM_CLOSE messages to GUI programs and CTRL_CLOSE_EVENT events to console programs. But you don't get a chance to intercept TerminateProcess. Why not?

    TerminateProcess is the low-level process killing function. It bypasses DLL_PROCESS_DETACH and anything else in the process. Once you kill with TerminateProcess, no more user-mode code will run in that process. It's gone. Do not pass go. Do not collect $200.

    If you could intercept TerminateProcess, then you would be escalating the arms race between programs and users. Suppose you could intercept it. Well, then if you wanted to make your program unkillable, you would just hang in your TerminateProcess handler!

    And then people would ask for "a way to kill a process that is refusing to be killed with TerminateProcess," and we'd be back to where we started.

    Tomorrow: About those processes that don't go away even though you've killed them. They're really dead, but they won't go away.

Page 417 of 464 (4,636 items) «415416417418419»