2
votes

I scroll the parent window by invalidating and redrawing all the content inside WM_PAINT according to current nPos value from scrollbar. I want to scroll without flickering so I handle WM_ERASEBKGND to avoid redrawing the background. I also do simple double buffering for my TextOut calls and for some bitmaps that are displayed. It works good except my child controls. They flicker badly especially when nPos == 0 and app handles SB_LINEUP or nPos == nMax and app handles SB_LINEDOWN or when dragging and dropping the scrollbar. I move them with MoveWindow(). I also have tried DeferWindowPos(). I've googled it for a solution for flickering but it doesn't work or I'm not using it correctly. How to eliminate flickering of child controls?

P.S. When I use WS_CLIPCHILDREN style for main window the controls aren't flickering but when scrolling some parts of my window get messed up, especially my static control on which I'm drawing some things by handling WM_DRAWITEM.

EDIT: (simplified code) I double buffer inside WM_PAINT like this:

case WM_PAINT: {
    hDC = BeginPaint( hwnd, &PS );
    hDCMem = CreateCompatibleDC( hDC );
    hBMMem = CreateCompatibleBitmap( hDC, wnd_x, wnd_y );
    SelectObject( hDCMem, hBMMem );

    Font = CreateFont( 130, 50, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_MODERN, "Arial" );
    SelectObject( hDCMem, Font );
    SetTextColor( hDCMem, RGB( 30, 144, 255 ) );
    SetBkColor( hDCMem, RGB( 192, 192, 192 ) );
    TextOut( hDCMem, 650, 69 - scr_pos, "ABC", 3 );

    MoveWindow( GetDlgItem( hwnd, ID_BUTT_START ), 720, 500 - scr_pos, 160, 150, TRUE );

    BitBlt( hDC, 0, 0, wnd_x, wnd_y, hDCMem, 0, 0, SRCCOPY );
    DeleteObject( hBMMem );
    DeleteDC( hDCMem );
    EndPaint( hwnd, &PS );
}

scr_pos is current nPos value taken from scrollbar.

case WM_ERASEBKGND:
    return 1;
break;

case WM_VSCROLL: {
    SCROLLINFO sinfo;
    ZeroMemory( &sinfo, sizeof( SCROLLINFO ) );
    sinfo.cbSize = sizeof( SCROLLINFO );
    sinfo.fMask = SIF_POS | SIF_PAGE | SIF_TRACKPOS;
    GetScrollInfo( hwnd, SB_VERT, &sinfo );
    scr_pos = sinfo.nPos;
    switch( LOWORD( wParam ) ) {
        case SB_TOP:
            scr_pos = 0;
        break;
        case SB_BOTTOM:
            scr_pos = 4000;
        break;
        case SB_LINEUP: {
            scr_pos -= 200;
            if ( scr_pos < 0 ) {
                scr_pos = 0;
            }
        }
        break;
        case SB_LINEDOWN: {
            scr_pos += 200;
            if ( scr_pos > 4000 ) {
                scr_pos = 4000;
            }
        }
        break;
        case SB_PAGEUP: {
            scr_pos -= si.nPage;
            if( scr_pos < 0 ) {
                scr_pos = 0;
            }
        }
        break;
        case SB_PAGEDOWN: {
            scr_pos += si.nPage;
            if( scr_pos > 4000 ) {
                scr_pos = 4000;
            }
        }
        break;
        case SB_THUMBPOSITION:
            scr_pos = HIWORD(wParam);
        break;
        case SB_THUMBTRACK:
            scr_pos = HIWORD(wParam);
        break;
    }    
    RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT );
//  InvalidateRect ( hwnd, NULL, true );
//  UpdateWindow( hwnd );
    ZeroMemory( & sinfo, sizeof( SCROLLINFO ) );
    sinfo.cbSize = sizeof( SCROLLINFO );
    sinfo.fMask = SIF_POS;
    snfo.nPos = scr_pos;
    SetScrollInfo( hwnd, SB_VERT, & sinfo, TRUE );
    }
}
break;

Nothing flickers except child controls...

1
If you're double-buffering, I can't imagine how this would flicker. It would be much easier to diagnose if you'd post actual code, rather than settling for an explanation of your code.Cody Gray♦
Are you sure you don't do unnecessary invalidating somewhere? Cody Gray is right, post the code.Flot2011
Code added. Let me know if I missed some important part.okt

1 Answers

5
votes

WS_CLIPCHILDREN is indeed the solution. Go ahead and activate that, you'll have to track down the cause of "parts of my window get messed up", but you haven't provided sufficient detail about that.

You might also look into ScrollWindowEx. That documentation specifically describes how to correctly reposition child windows during scrolling.