Search code examples
winapipaintmsdn

WM_PRINTCLIENT (and related) documentation confusion-related questions


I'm a bit confused by the MSDN page for WM_PRINTCLIENT and related functionality in a few ways:

  1. What value should I return from my window procedure? The documentation is missing a "Return value" section entirely. (It is also missing in the Visual Studio 2012 offline documentation disc's version of the page.) Raymond Chen's original scratch program returns zero; is this the preferred option?

  2. The summary and Remarks section for WM_PRINTCLIENT indicates that I should only draw the client area, but the LPARAM lists all the possible WM_PRINT flags — so what should I do, ignore it and unconditionally draw just the client area or draw everything requested? (My intention with this question is not to second-guess the documentation; I'm just looking to implement this message correctly.)

  3. I want to, as a convenience/kindness, provide the WM_PAINT with DC in wParam functionality mentioned in the WM_PAINT documentation as an option as well. How should I interpret LPARAM in this case? Or is there a reason I shouldn't provide this alternative route? (Corollary: if LPARAM is to be ignored, should I draw the entire client area unconditionally?)

Thanks.

Update Rephrasing the third part:

The documentation for WM_PAINT includes the paragraph

For some common controls, the default WM_PAINT message processing checks the wParam parameter. If wParam is non-NULL, the control assumes that the value is an HDC and paints using that device context.

I would like to provide this behavior in my control in addition to WM_PRINTCLIENT for completeness's sake. Is there a reason I should NOT do so? And if doing so wouldn't hurt, how should I interpret the lParam, and should I draw the entire client rect?


Solution

  • What value should I return from my window procedure?

    You return 0 to indicate that the message was handled. Do not call DefWindowProc().

    but the LPARAM lists all the possible WM_PRINT flags

    That was a bit sloppy, a copy/paste fumble from the WM_PRINT article. The only flags you should test are PRF_ERASEBKGND, but only if your draw method requires having the background painted, and PRF_CLIENT, which will always be set in common usage of the message.

    How should I interpret LPARAM in this case?

    Hard to decode that question, WM_PAINT doesn't use the lparam argument. But yes, you want a common function that implements the painting so you can call it both from your WM_PAINT and your WM_PRINTCLIENT message handlers. Boilerplate code in your window procedure ought to look like:

    case WM_PAINT: {
        HDC hdc = BeginPaint(hWnd, &ps);
        Draw(hdc);
        EndPaint(hWnd, &ps);
        break;
    }
    case WM_PRINTCLIENT: {
        HDC hdc = (HDC)wParam;
        DWORD flags = (DWORD)lParam;
        if (flags & PRF_ERASEBKGND) SendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hdc, NULL);
        if (flags & PRF_CLIENT)     Draw(hdc);
        break;
    }
    

    Where void Draw(HDC hdc) is your common paint function.