Controls disappear after scrolling in Cwnd with ScrollWindowEx

后端 未结 1 1280
误落风尘
误落风尘 2021-01-16 05:34

I\'ve implemented a CScrollBar in a Cwnd, but after scroll the controls on the window disappear. I\'ve heard I could use DeferWindowPos someway, but I don\'t know how to do

相关标签:
1条回答
  • 2021-01-16 06:27

    Moving child windows using CWnd::ScrollWindowEx using the SW_SCROLLCHILDREN flag is problematic:

    If the SW_SCROLLCHILDREN flag is specified, Windows will not properly update the screen if part of a child window is scrolled. The part of the scrolled child window that lies outside the source rectangle will not be erased and will not be redrawn properly in its new destination. Use the DeferWindowPos Windows function to move child windows that do not lie completely within the lpRectScroll rectangle.

    The solution is to move child windows manually. DeferWindowPos has the same effect as calling SetWindowPos for multiple windows, but is optimized to perform the layout in a single call. This helps reduce visual artifacts, where controls appear to move relative to each other, until everything is settled.

    DeferWindowPos requires a structure holding the new window properties. It is created calling BeginDeferWindowPos, then updated for each window with a call to DeferWindowPos, and finally sent off to the system to perform the repositioning with EndDeferWindowPos. The following code assumes an array containing CWnd*s of all child controls in an array, with cx and cy holding the horizontal and vertical offset. It is meant to replace the call to ScrollWindowEx:

    CWnd* controls[] = { m_pEdit, m_pButton, ... };
    
    HDWP hDwp = ::BeginDeferWindowPos( ARRAYSIZE( controls ) );
    
    for ( size_t index = 0; index < ARRAYSIZE( controls ); ++index ) {
        // Find the current window position
        CRect wndRect;
        controls[index]->GetWindowRect( wndRect );
        // DeferWindowPos requires client coordinates, so we need to convert from screen coords
        ScreenToClient( wndRect );
        // Set the control's new position
        hDwp = ::DeferWindowPos( hDwp, *controls[index], NULL,
                                 wndRect.left + cx, wndRect.top + cy, 0, 0,
                                 SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE |
                                 SWP_NOZORDER );
    }
    
    // All new control positions have been recorded. Now perform the operation
    ::EndDeferWindowPos( hDwp );
    
    0 讨论(0)
提交回复
热议问题