• The Old New Thing

    What's so special about the desktop window?

    The window returned by GetDesktopWindow() is very special, and I see people abusing it all over the place.

    For example, many functions in the shell accept a window handle parameter to be used in case UI is needed. IShellFolder::EnumObjects, for example.

    What happens if you pass GetDesktopWindow()?

    If UI does indeed need to be displayed, you hang the system.


    • A modal dialog disables its owner.
    • Every window is a descendant of the desktop.
    • When a window is disabled, all its descendants are also disabled.

    Put this together: If the owner of a modal dialog is the desktop, then the desktop becomes disabled, which disables all of its descendants. In other words, it disables every window in the system. Even the one you're trying to display!

    You also don't want to pass GetDesktopWindow() as your hwndParent. If you create a child window whose parent is GetDesktopWindow(), your window is now glued to the desktop window. If your window then calls something like MessageBox(), well that's a modal dialog, and then the rules above kick in and the desktop gets disabled and the machine is toast.

    So what window do you pass if you don't have a window?

    Pass NULL. To the window manager, a parent of NULL means "Create this window without an owner." To the shell, a UI window of NULL typically means "Do not display UI," which is likely what you wanted anyway.

    Be careful, though: If your thread does have a top-level unowned window, then creating a second such window modally will create much havoc if the user switches to and interacts with the first window. If you have a window, then use it.

  • The Old New Thing

    Invalid thread and process IDs

    Perhaps you want a value to use as a sentinel, which you want to be guaranteed is never a valid thread ID or process ID. What values can you use?

    Nothing is explicitly written about this topic, but you can put on your logic cap and figure it out.

    If you need an invalid thread ID, you can use zero. How do you know that zero is an invalid thread ID? It's implied by SetWindowsHookEx: Notice that if you pass zero, then the hook is installed into all threads on the current desktop. This implies that zero is not itself a valid thread ID.

    This sentinel value is confirmed by GetThreadID, which uses zero as its error return value.

    Similarly, if you need an invalid process ID, you can use (DWORD)-1. This comes from AllowSetForegroundWindow: The value ASFW_ANY has special meaning, which implies that it is never a valid process ID.

    Or, you can use zero as your invalid process ID, since that is the error value returned by GetProcessId and GetProcessIdOfThread.

  • The Old New Thing

    And we will build a processor with... ONE MILLION TRANSISTORS!

    A friend of mine decided to recaption this picture which is in the rotation on Intel's Hardware Design Home Page:

    "And we will build a processor with... ONE MILLION TRANSISTORS!"

    Who knew that Dr. Evil designed CPUs, too!

  • The Old New Thing

    Raymond's comment policy


    Okay, I was hoping it wasn't going to be needed but it takes only one bad apple...

    Here are the ground rules.

    • I reserve the right to edit, delete, or ignore any comment.
    • If I edit your comment in any significant way, I promise to make that fact clear in the edit. (Exception: Broken links and typos will be repaired without comment.)

    Things that increase the likelihood that your comment will be edited or deleted:

    • Offensive or abusive language or disrespectful behavior. (Insults count as disrespectful behavior. Examples of insulting words/phrases: "moron", "designed without adult supervision".)
    • Misrepresentation. (I.e., claiming to be somebody you're not.) If you don't want to use your real name, that's fine, as long as your "handle" isn't offensive, abusive, or misrepresentative.
    • Comment spamming. This includes posting multiple comments in rapid succession, even if they are different. If you are prone to spurts of creativity, collect them into batches and post them as a single comment.
    • Comments that are off-topic, particular when the discussion turns into a shouting match.
    • Comments that attempt to "out" a company/program/person. E.g., trying to guess the identity of a program whose name I did not reveal.
    • More generally, comments that identify a specific company, program, or person. You can talk about a program, but you have to call it "Program X" or something like that. The purpose is to discuss problems and solutions, not to assign blame and ridicule.
    • Comments that expose me to potential legal action. Examples: Disclosing any company's trade secrets, posting copyrighted source code, violating Microsoft's company guidelines.
    • Giving yourself a star. (This is another case of mispresentation.)

    If a wave of comment spam is under way, I may choose to moderate or even close comments until the problem subsides.

    More rules may be added later, but I hope it won't be necessary.

    Disclaimer: All postings are provided "AS IS" with no warranties and confer no rights. Opinions expressed are those of the respective authors. More legal stuff here.

    [31 May 2004: Add exceptions for broken link repair.

    2 Dec 2004: Add disclaimer and exception for fixing typos.

    13 Dec 2004: Add remark on temporary closure of comments during spam attacks.

    15 Mar 2005: Add remark for off-topic comments.

    20 Mar 2007: No "outing".

    25 Dec 2008: No disrespectful behavior.

    12 March 2009: Examples of insults.

    8 July 2010: Self-starring.]

  • The Old New Thing

    Why do I get a QueryInterface(IID_IMarshal) and then nothing?

    A common problem when trying to get your new COM object off the ground is that you can't seem to be able to get it created. The object comes out of the class factory, and it gets a QueryInterface for IMarshal, and then nothing. What's going on?

    This is a sure sign that you didn't register your CLSID properly; most likely you forgot to set your threading model properly. (And if you fail to specify a threading model at all, then you get the dreaded "main" threading model.)

    If somebody tries to create a COM object from a thread whose model is incompatible with the threading model of the COM object, then a whole bunch of marshalling stuff kicks in. And if the marshalling stuff isn't there, then COM can't use your object.

    There is a long and very technical article in MSDN on COM threading models which has lots of scary-looking diagrams and tables. In particular, the second scary table in the "In-process servers: (almost) totally dependent on their clients" chapter lists all the combinations of thread models with object threading models, and what COM tries to do in each case.

    In particular, notice that if you have a (mistakenly marked) "main"-threaded object and somebody on any thread other than the main thread tries to create it, marshalling will try to kick in.

    So watch those threading models. The failure modes when you get them wrong are quite baffling.
  • The Old New Thing

    Sorry the posts are late lately

    Somehow the server is in a wonky state and my autopilot script that posts a new article at 7 every morning is getting error 500 back (internal server error). So I'm posting manually for the nonce. Expect erratic posting times until the problem is resolved.
  • The Old New Thing

    No code is an island

    Norman Diamond noted in a comment that on Windows 2003 Server, the Display Adapter Troubleshooting slider still lists "full acceleration" as the recommended setting even though the default for Server is "full minus one".

    This is one of those "Oh, that's an easy change" bugs. The discussion probably went like this:

    Some guy whose idea this was: "For stability reasons, we want to lower the default video acceleration for Server a notch. Dear Video Setup team, can you do that for us?"

    Video Setup team: "Sure thing, that's no problem. The default setting is all done by us; it should not have any impact on anybody else. We'll just do it and be done with it."

    Guy: "Sweet. Thanks."

    And bingo, the default video acceleration dropped to one notch below full on Server, and everyone was happy.

    Except that there's this text tucked away in the Display control panel that has the word "(recommended)" next to "full acceleration". That didn't get updated. Oops. (I wouldn't be surprised if there is also some help text that didn't get updated for this change.)

    No code is an island.

    So when you complain, "Aw come on, it's a one-line change. What's taking so long?" think about the little video acceleration slider.
  • The Old New Thing

    Why are RECTs endpoint-exclusive?


    Endpoint-exclusive RECTs and lines are much easier to work with.

    For example, the width of a rectangle is right - left, and its height is bottom - top. If rectangles were endpoint-inclusive, then there would be annoying +1's everywhere.

    End-point exclusive rectangles also scale properly.

    For example, suppose you have two rectangles (0,0)-(100,100) and (100,100)-(200,200). These two rectangles barely touch at the corner. Now suppose you magnify these rectangles by 2, so they are now (0,0)-(200,200) and (200,200)-(400,400). Notice that they still barely touch at the corner. Also the length of each edge doubled from 100 to 200.

    Now suppose endpoints were inclusive, so the two rectangles would be (0,0)-(99,99) and (100,100)-(199,199). Now when you double them, you get (0,0)-(198,198) and (200,200)-(398,398). Notice that they no longer touch any more because (199,199) is missing. Note also that the length of the side of the square is now 199 pixels instead of 200.

    Similar problems occur if you need to do subpixel computations.

    "But that's silly -- who ever does magnification or subpixel computations?"

    Well, magnification is used more than you think. In addition to the obvious things like zooming in/out, it's also used in printing (since printers are 300dpi but the screen is usually much lower resolution) and in GDI mapping (ScaleWindowExtEx, StretchBlt). And subpixel computations are used in anti-aliasing.

    With apologies to Alvy Ray, I think the best way to interpret this is to view pixels as living between coordinates, not at them. For example, here's a picture of the pixel that lives between (10,10) and (11,11). (In other words, this pixel is the rectangle (10,10)-(11,11).)

      10 11

    With this interpretation, the exclusion of the endpoint becomes much more natural. For example, here's the rectangle (10,10)-(13,12):

      10 11 12 13

    Observe that this rectangle starts at (10,10) and ends at (13,12), just like its coordinates say.

  • The Old New Thing

    GetDialogBaseUnits is a crock

    There are two functions that let you convert dialog units (DLUs) to pixels. One is GetDialogBaseUnits, which returns the base units directly (leaving you to do the math), and another is MapDialogRect, which takes a rectangle in DLUs and returns a rectangle in pixels.

    What's the difference?

    As you can guess from the title of this entry, GetDialogBaseUnits is a crock. Since there is no HWND parameter to GetDialogBaseUnits, it doesn't know which dialog box's DLUs you want to retrieve. So it guesses.

    And it always guesses wrong.

    GetDialogBaseUnits returns the dialog base units for dialog boxes that use the default system font. But nobody uses the default system font any more. It screams "old and dorky". But it remains the default for compatibility reasons. (And therefore so too does GetDialogBaseUnits.)

    Everybody selects a custom font for their dialog box, usually "MS Sans Serif 8" or possibly "Tahoma" if they are one of those hip Windows 2000 folks.

    That is why you must use MapDialogRect. The MapDialogRect function accepts a dialog box handle so it can use the correct font.

  • The Old New Thing

    The social skills of a thermonuclear device


    Somebody@somewhere.else described me as having the social skills of a thermonuclear device. I don't remember the incident in question, but I'll have to accept that it happened.

    I have a very low tolerance for laziness. If you come to me for help, I expect you to have done your homework. (Though I try to scale my expectations to your position. If you're in a coding position then you had better know how to use a debugger. If you're in a testing position, then you had better know at least how to install the debugger. This is considered part of the standard skill set for a tester.)

    But the absolute worst thing you can do is start a conversation by saying, "Hey, Raymond, since you know everything, can you do this for me...?"

Page 420 of 446 (4,451 items) «418419420421422»