• Is win32-gdi system-driven WM_PAINT flicker free?

    From R.Wieser@21:1/5 to All on Wed Mar 10 13:06:40 2021
    Elemich,

    if you move mouse inside the window, severe flicker will
    occurr (repaint sended by me)

    Question: why do you think you should force a repaint on any kind of mouse movement ?
    Suggestion: don't.

    Question: why are you (trying to) invalidate the rectangle *inside* the very event that is called as a response to it ? I think you're lucky that the re-validation step happens at the end, otherwise you would have had a
    blinkfest ...
    Suggestion: remove it.

    And I hope you realize that putting a Sleep() in that (or any) event is a
    big no-no. User timers (that fire events and do your stuff in there).

    Furthermore, its rather informative to us when you mention what the
    codesample is supposed to be doing.

    is not possible to pretty-formatting the code?

    This is a newsgroup, not some HTML RTF forum. :-) Besides, whats wrong
    with the formatting you used ? It looks pretty readable to me. For everything else just use code comments.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Elemich@21:1/5 to All on Wed Mar 10 03:29:48 2021
    running this code leads to the title question:

    if you resize the window you will not see any flicker (repaint sended by the system)
    if you move mouse inside the window, severe flicker will occurr (repaint sended by me)

    how to reproduce the system-driven WM_PAINT?

    #include <windows.h>
    #include <wingdi.h>

    LRESULT CALLBACK proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
    switch(msg)
    {
    case WM_ERASEBKGND: return true;break;
    case WM_MOUSEMOVE: InvalidateRect(hwnd, 0, 0); break;
    case WM_PAINT:
    {
    InvalidateRect(hwnd,0,0);
    HBRUSH b= CreateSolidBrush(0x000000ff);
    HBRUSH c= CreateSolidBrush(0x0000ff00);
    HBRUSH d= CreateSolidBrush(0x00ff0000);
    RECT r;
    GetClientRect(hwnd,&r);
    PAINTSTRUCT ps;
    HDC hdc=BeginPaint(hwnd,&ps);
    FillRect(hdc,&r, b);
    Sleep(10);
    FillRect(hdc,&r, c);
    ` Sleep(10);
    FillRect(hdc,&r,d);
    EndPaint(hwnd,&ps);
    DeleteObject(b);
    DeleteObject(c);
    DeleteObject(d);
    }
    break;
    default:
    return DefWindowProc(hwnd, msg, wparam, lparam);
    }
    return 0;
    }
    int main()
    {
    HWND hwnd=CreateWindow(WC_DIALOG,0,WS_OVERLAPPEDWINDOW|WS_VISIBLE,0,0,500,500,0,0,0,0);
    SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)proc);

    MSG msg;

    while (true)
    {
    if (GetMessage(&msg, 0, 0, 0) != WM_CLOSE)
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    }
    return 1;
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Elemich@21:1/5 to All on Wed Mar 10 03:36:50 2021
    is not possible to pretty-formatting the code?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Elemich@21:1/5 to All on Wed Mar 10 04:33:07 2021
    dear Wieser, this code is to show that the WM_PAINT after the WM_SIZE is a particular type of WM_PAINT, handed differently from other WM_PAINTs,
    for this reason the Sleep serves to show the flickering and the invalidateRect inside the paint routine serves to forcing to repaint the entire area as you can see checking the ps.rcPaint rectangle.
    have you tried to compile and running this snippet?
    thank you for your time

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Wed Mar 10 18:02:35 2021
    Elemich,

    this code is to show that the WM_PAINT after the WM_SIZE is a particular
    type of WM_PAINT, handed differently from other WM_PAINTs

    I can see you have taken the normal paint event and filled it with your own code (ignoring the default). I do not see how its a "particular type of"
    paint though.

    for this reason the Sleep serves to show the flickering and the invalidateRect
    inside the paint routine serves to forcing to repaint the entire area as
    you can
    see checking the ps.rcPaint rectangle.

    What I see is that *you* are purposely creating a (color) flickering.

    have you tried to compile and running this snippet?

    Why would I do that ? I allready know that it will flicker.

    I *think* you want to point out some kind of problem, but you still have to describe what that problem actually is (what I should be looking for/at).
    And no, pointing to that (color) flicker you yourself introduced doesn't
    help in the slightest I'm afraid.

    All I can currently tell you is *not* to put time-consuming (drawing)
    actions in the paint event.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Elemich@21:1/5 to All on Wed Mar 10 09:44:18 2021
    Why would I do that ? I allready know that it will flicker.

    if you'll try you discover resizing the windows will not flickers

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Elemich@21:1/5 to All on Wed Mar 10 09:41:51 2021
    Rudy

    i think you have not grasped the question:

    the paint routine in WM_PAINT handler shows that if it happens from a WM_SIZE , that is, a system-driven event at least in this case, the result will not flicker;
    if the WM_PAINT happens from the WM_MOUSEMOVE event, that is, a user-driven event at least in this case, the result will flicker abundantly.

    now the question is: is system-driven WM_PAINT acts differently from a user-driven WM_PAINT?

    i hope you understand now.

    thank you

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Wed Mar 10 20:23:14 2021
    Elemich,

    the paint routine in WM_PAINT handler shows that if it happens
    from a WM_SIZE , that is, a system-driven event at least in this
    case, the result will not flicker;
    if the WM_PAINT happens from the WM_MOUSEMOVE event,
    that is, a user-driven event at least in this case, the result will
    flicker
    abundantly.

    Yeah, funny how that can happen when you call 'InvalidateRect' in the 'mousemove', but *not* in the 'size' event. In other words, you are
    cheating. :-)

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Wed Mar 10 21:24:39 2021
    Elemich,

    To show you what the effect of that 'InvalidateRect' is would like you to
    make a few changes to your code.

    Create a 'global' variable, initialize it with 0xFF0000 and use it as the
    color for brush "d". After each "d" brush creation add something to that
    color (I add 0x10 to the third byte, the FF / blue color)

    On my puter I see the window change color when I move the mouse over it, or when I enlarge the window. No color change when I shrink the window.

    When I remove the 'InvalidateRect' inside the 'paint' event the whole window still changes color when I move the mouse over it. But now take a look at what happens when you enlarge the window ...

    If you see the same as I do you see colored bands appear where you enlarged
    the window, *but not where that window already existed*.

    IOW, your code still *tries* to color the whole window, but due to only the newly-added space being invalidated (by "the system") the drawing changes
    only occur there. And likely you do not see any flickering (that you programmed) *even though its still there* because there is too much change going on - the border of the window moving and making place for some empty window space.

    Also notice that when you move the left border left or the top border up the colored bands appear on the right or bottom. IOW : The moved part of the window is /not/ redrawn at all. That is, as long as you do not invalidate
    the whole window. Take a guess what happens when you also put an 'InvalidateRect' in the 'size' event. :-)

    Also:
    [quote]
    if you resize the window you will not see any flicker (repaint sended by the system)
    if you move mouse inside the window, severe flicker will occurr (repaint
    sended by me)
    [/quote]
    In neither case *you* are sending the repaint request. In the latter case
    its send by "the system" as a result of it recognising that some visible
    area has been marked as "changed" (that is what "invalidated" is supposed to mean).

    Suggestion : invalidate *a small part* of the window. Like a square of
    10*10 pixels in the top-left corner.

    Before you execute that, imagine what you think will happen. Also try to reason why you think it would happen. And ? Does the result match your imagination ?

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JJ@21:1/5 to Elemich on Thu Mar 11 14:30:19 2021
    On Wed, 10 Mar 2021 03:29:48 -0800 (PST), Elemich wrote:
    running this code leads to the title question:

    if you resize the window you will not see any flicker (repaint sended by the system)
    if you move mouse inside the window, severe flicker will occurr (repaint sended by me)

    how to reproduce the system-driven WM_PAINT?

    Because the code directly draw on the application window, AND with added delays, you'll see the progress as flickers.

    Use a technique called double buffering. Make the code draw on a separate
    (off screen) bitmap first, then draw the bitmap onto the application window. It'll be a relatively slower process, but it'll minimize flickers. i.e. the display will be updated less frequently, but it'll minimize flickers.

    However, if the area which need to be redrawn is large enough, it will still cause noticable flicker if the computer is not fast enough. IOTW, the whole process still take too much time to complete for the computer. That's where you'll notice the progress of the process. That's what flickers are when
    those process are done repeatedly.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Thu Mar 11 10:22:08 2021
    JJ,

    how to reproduce the system-driven WM_PAINT?

    Because the code directly draw on the application window,
    AND with added delays, you'll see the progress as flickers.

    Use a technique called double buffering.

    The question is not how to minimize the flicker, but why "the system"s paint doesn't, and his paint does flicker (even though he and "the system" execute the same, his paint code). He simply doesn't yet know what effect "invalidaterect" (the whole screen) has. Currently he just uses it to
    force a paint event to happen, but forgets to recon with its "side effects".

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Fri Mar 12 15:12:49 2021
    JJ,

    That's exactly why.

    Nope. You're offering a solution to a problem he doesn't have.

    The problem he has is that he doesn't understand why the very code he wrote himself seems to act differently when its called "by himself" or "by the
    OS".

    He seems to assume that the OS either executes its own, different code, or
    does something special to make sure that the flickering doesn't occur.
    Neither is true. The cause/answer is way simpler. Which is what I tried to explain

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JJ@21:1/5 to R.Wieser on Fri Mar 12 20:42:29 2021
    On Thu, 11 Mar 2021 10:22:08 +0100, R.Wieser wrote:
    JJ,

    how to reproduce the system-driven WM_PAINT?

    Because the code directly draw on the application window,
    AND with added delays, you'll see the progress as flickers.

    Use a technique called double buffering.

    The question is not how to minimize the flicker, but why "the system"s paint doesn't, and his paint does flicker (even though he and "the system" execute the same, his paint code). He simply doesn't yet know what effect "invalidaterect" (the whole screen) has. Currently he just uses it to force a paint event to happen, but forgets to recon with its "side effects".

    That's exactly why.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)