Win32 API: как избежать мерцания основных элементов управления окнами? - PullRequest
2 голосов
/ 09 марта 2012

Я прокручиваю родительское окно, делая недействительным и перерисовывая весь контент внутри WM_PAINT в соответствии с текущим значением nPos из полосы прокрутки. Я хочу прокручивать без мерцания, поэтому я обрабатываю WM_ERASEBKGND, чтобы избежать перерисовки фона. Я также делаю простую двойную буферизацию для моих вызовов TextOut и для некоторых отображаемых растровых изображений. Это работает хорошо, за исключением моего контроля ребенка. Они плохо мерцают, особенно когда nPos == 0 и приложение обрабатывает SB_LINEUP или nPos == nMax и приложение обрабатывает SB_LINEDOWN или при перетаскивании полосы прокрутки. Я перемещаю их с MoveWindow (). Я также попробовал DeferWindowPos (). Я нашел его в поисках мерцания, но он не работает, или я не правильно его использую. Как устранить мерцание дочерних элементов управления?

P.S. Когда я использую стиль WS_CLIPCHILDREN для главного окна, элементы управления не мерцают, но при прокрутке некоторые части моего окна портятся, особенно мой статический элемент управления, на котором я рисую некоторые вещи, обрабатывая WM_DRAWITEM.

РЕДАКТИРОВАТЬ: (упрощенный код) Я удваиваю буфер внутри WM_PAINT так:

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 - текущее значение nPos, взятое с полосы прокрутки.

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;

Ничего не мерцает, кроме дочерних элементов управления ...

1 Ответ

4 голосов
/ 09 марта 2012

WS_CLIPCHILDREN действительно является решением. Продолжайте и активируйте это, вам придется отследить причину "испорчены части моего окна", но вы не предоставили достаточно подробностей об этом.

Вы также можете заглянуть в ScrollWindowEx. В этой документации конкретно описывается, как правильно перемещать дочерние окна во время прокрутки.

...