Why does PrintWindow hate CS_PARENTDC? redux

Why does Print­Window hate CS_PARENT­DC? Because everybody hates CS_PARENT­DC!

Commenter kero claims that it's "easy to fix" the problem with Print­Window and CS_PARENT­DC. You just remove the CS_PARENT­DC style temporarily, then do the normal Print­Window, then restore the CS_PARENT­DC style. The question is then why Print­Window simply doesn't do this.

The question assumes that the described workaround actually works. It may work in limited situations, but it certainly doesn't work in general.

Since the CS_PARENT­DC style is a class style, removing the style affects all windows of that class, not merely the window you are trying to print. Suppose there are two windows of the class running on different threads, and you remove the CS_PARENT­DC style in anticipation of doing a Print­Window. While that's going on, the other window gets a WM_PAINT message. Since the CS_PARENT­DC style was temporarily removed, that window will be painting with an incorrectly-clipped DC. Result: Incorrect pixels on the screen.

The proposed workaround doesn't actually work reliably, which means that it probably shouldn't be done at all. (Random reinforcement breeds superstition.)

Comments (9)
  1. Joshua says:

    [The proposed workaround doesn't actually work reliably, which means that it probably shouldn't be done at all.]

    Too bad I can't convince my bosses of that.

  2. Ben Voigt says:

    Far too many programmers out there work on the reverse assumption:  If code doesn't fail reliably, use it (and reuse it, and copy it for use elsewhere).

  3. immibis says:

    Of course, not everyone is using multiple threads. Or even multiple windows.

  4. Gabe says:

    I'm still not clear on why PrintWindow hates CS_PARENTDC. Here's what the docs (msdn.microsoft.com/…/ff729176.aspx) say:

    Sets the clipping rectangle of the child window to that of the parent window so that the child can draw on the parent. A window with the CS_PARENTDC style bit receives a regular device context from the system's cache of device contexts. It does not give the child the parent's device context or device context settings. Specifying CS_PARENTDC enhances an application's performance.

    It looks like this style means you're just asking for a special clipping rectangle (region?). I don't see what's to hate.

  5. Antonio 'Grijan' says:

    I have never understood the need for PrintWindow. Of course, WYSIWYG editors are supposed to use the same code to draw in both screen and printer. But they are different enough to make you use separate wrapper code. For starts, a window on the screen usually shows only part of the document, or maybe a page scaled to fit inside it. And the window may need to draw additional elements (page borders, window background outside the page, document/margin limits, table rows and columns…). PrintWindow is, IMHO, a quick and dirty job, and everyone lazy enough to use it should be punished (hey, many times, using it is its own punishment!).

    @Gabe: read the linked article. It's not about clipping regions, but about the window using the wrong DC (in this case, a screen DC instead of the printer's DC).

  6. cheong00 says:

    @Antonio 'Grijan' : The old ASPX programming model does try to make writing WebForm similar to writing WinForm applications. However the experience is… quite leaky… I should say. If you don't know how to program in web, your application still cannot get smooth user experience, but that doesn't mean Microsoft should stop support it.

  7. Joshua says:

    @chenog00: Ever see somebody call MsgBox from a VB ASPX program? We had one developer not be able to figure out why it didn't work when we deployed it even though it did on his workstation. We went back and checked. He turned on "Allow service to interact with desktop" on IIS on his workstation.

  8. Gabe says:

    Antonio 'Grijan': I did read the linked article — I even commented on it. And I still don't see any part that says how the CS_PARENTDC style causes problems when a paint function is passed a printer's DC. It's not like CS_OWN­DC, where you would have been expecting a pre-existing DC that might already have things like brushes selected (that obviously wouldn't work with a printer's DC).

    As I said, the CS_PARENTDC documentation states that the distinguishing factors about that style are that you get a different window's clipping rectangle, not that you get a special DC.

  9. cheong00 says:

    @Joshua: All I could say is "Oops". :P

    Btw, this kind of question happens a lot in MSDN forum alone. There are other variant of it like launching notepad or printing to a selected printer… Some can be solved and others cannot. Hopefully after encounter this once they'll understand these are two worlds.

Comments are closed.