locked
When Is WM_PAINT FinishedI? RRS feed

  • Question

  • Hi Folks:

       Developing on Windows 10 Pro, VS 2017 Community, all C++, WIN 32 no MFC. 

       I'd like to know when WM_PAINT has finished repainting a window. 

       I'd like to know this so, when the UI thread's dialog has finished painting, it can post a message to a diagnostic thread.  The diagnostic thread can stop on a breakpoint, and I can see what the state of the UI's thread. 

       I've tried to introduce a bit of a delay by having the code that services the WM_PAINT message post a message to it's own dialog, and that posts a message to the diagnostic thread that there's something happening. 

       The UI thread's dialog is blank when the diagnostic thread stops. 

       Last October RLWA32 pointed me to Raymond Chen's article in The New Old Thing that showed me how to know when a new window is ready to receive input. 

       This is different.  The window has been visible, now I need to know if a repaint is finished.

       Thanks
       Larry





    Thursday, May 16, 2019 3:05 AM

All replies

  • Hi,

    Thank you for posting here.

    >>When Is WM_PAINT FinishedI?

    You handle WM_PAINT by calling BeginPaint, then painting, and then calling EndPaint. The region that you paint is marked as valid when you call EndPaint.

    Windows generates WM_PAINT messages when you process the message queue. It will only generate WM_PAINT messages when there are invalid regions. Once you have painted, there are no more invalid regions, and so no WM_PAINT messages are generated.

    Note that Windows, typically, does not send WM_PAINT messages. These are asynchronous messages that are retrieved when your application's message loop pulls messages from the message queue. For instance, when you call GetMessage, and the message queue is empty, and there are invalid regions, then WM_PAINT messages are generated.

    The exception to the statement above is when calls to UpdateWindow and RedrawWindow are made. In those scenarios, WM_PAINT messages are sent synchronously.

    For more details you could refer to the link:https://docs.microsoft.com/en-us/windows/desktop/gdi/wm-paint

    Best Regards,

    Jeanine Zhang
    Thursday, May 16, 2019 5:58 AM
  • You mention a UI thread's dialog.  Is it your dialog?  Modal or modeless?

    What is the larger problem that you are trying to solve by acting only when WM_PAINT processing has completed?

    Thursday, May 16, 2019 10:02 AM
  • You could subclass your window so that the subclass proc would see WM_PAINT messages and could process both before and after they were handled.

    For example, in the Win32 application created by the wizard I added some debug output to the WM_PAINT handler in WndProc and also to the subclass procedure.

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
    		Report(TEXT("Before BeginPaint\n"));
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code that uses hdc here...
            EndPaint(hWnd, &ps);
    		Report(TEXT("After EndPaint\n"));
        }
        break;
    

    And the subclass -

    LRESULT CALLBACK SubProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uiSub, DWORD_PTR dwRefData)
    {
    	if (msg == WM_PAINT)
    		Report(TEXT("Before WM_PAINT, HWND : %p"), hwnd);
    
    	LRESULT ret = DefSubclassProc(hwnd, msg, wParam, lParam);
    	
    	if (msg == WM_PAINT)
    		Report(TEXT("After WM_PAINT, HWND : %p"), hwnd);
    
    	return ret;
    }
    

    Debug output messages generated were -

    [1304] Before WM_PAINT, HWND : 001001EC
    [1304] Before BeginPaint
    [1304] After EndPaint
    [1304] After WM_PAINT, HWND : 001001EC
    [1304] Before WM_PAINT, HWND : 001001EC
    [1304] Before BeginPaint
    [1304] After EndPaint
    [1304] After WM_PAINT, HWND : 001001EC
    


    Thursday, May 16, 2019 10:51 AM
  • One of the issues with dialog boxes is that there is more to them than meets the eye. While you do have a dialog procedure to define behaviour, there is still a window procedure driving this and calling your dialog procedure.

    Your dialog procedure isn't the thing driving the drawing, it is the default dialog procedure (DefDlgProc), this is the window procedure for a dialog box. If I remember correctly, the way a window with children gets drawn is:

    1) WM_ERASEBKGND for the area affected

    2) WM_PAINT for the parent window

    3) WM_PAINT for each of the child windows

    4) WM_NCPAINT for the borders if needed

    So painting for the window would technically be over when all of the paint messages have exited.

    But without knowing what DefDlgProc does and without knowing when it returns then posting (PostMessage) a message to yourself is probably the best option. By the time you process that message after WM_PAINT, then you will know that the painting has finished.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    • Edited by Darran Rowe Thursday, May 16, 2019 11:47 AM
    Thursday, May 16, 2019 11:46 AM
  • Hi,

    Have you got any updates? If your case has been solved, please help to mark answers. If not, just feel free to contact us.

    Your understanding and cooperation will be grateful.

    Best Regards,

    Jeanine Zhang

    Wednesday, May 29, 2019 9:07 AM