#131 CScrollImpl, dialogs and WS_EX_TRANSPARENT

open
None
5
2006-07-09
2006-07-06
xanatos
No

There are some problems with CScrollImpl, a dialog
box with WS_CLIPCHILDREN, WS_CLIPSIBLINGS, a groupbox
with WS_EX_TRANSPARENT with some controls (for
example buttons) on it. See the example for the code.
Make the window half the height. Scroll down to the
end. Now drag the lower border to make the window
taller. The groupbox will go "mad". This is strange
because when you simply scroll the dialog there isn't
any problem.

Discussion

  • xanatos
    xanatos
    2006-07-06

    Example

     
    Attachments
  • xanatos
    xanatos
    2006-07-06

    Logged In: YES
    user_id=1223597

    The problem is that the SetWindowPos of line 170 doesn't
    consider the fact that some controls could be Transparent.
    You could try to do this:
    HDWP hdwp = ::BeginDeferWindowPos(0);
    for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD);
    hWndChild != NULL; hWndChild = ::GetWindow(hWndChild,
    GW_HWNDNEXT))
    {
    RECT rect = { 0 };
    ::GetWindowRect(hWndChild, &rect);
    ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
    ::DeferWindowPos(hdwp, hWndChild, NULL, rect.left + dx,
    rect.top + dy, rect.right - rect.left, rect.bottom -
    rect.top, SWP_NOZORDER | SWP_NOOWNERZORDER |
    SWP_NOACTIVATE | ::GetWindowLong(hWndChild, GWL_EXSTYLE) &
    WS_EX_TRANSPARENT ? SWP_NOCOPYBITS : SWP_NOSIZE);
    }
    ::EndDeferWindowPos(hdwp);

    Forcing a size change with the SWP_NOCOPYBYTS WILL cause
    the redraw of the Group Box. Don't ask me why you need
    both of them :-)

    There is another similar for loop in the SetScrollSize.
    Still I think the best idea would be to use the
    ScrollWindowEx instead of the for loops... It seem to work
    better. You could use the for loop when bRedraw is TRUE
    (using the SWP_NOREDRAW flag and SetWindowPos) and the
    invalidate the window and if the window mustn't be
    redrawed then ScrollWindowEx. I'll it.

     
  • xanatos
    xanatos
    2006-07-06

    Logged In: YES
    user_id=1223597

    Third comment... Yes, you can hate me... But now with a
    solution (I'm not sure it'll work everywhere... It seems
    to work :-))

    In the SetScrollOffset instead of the
    if(IsScrollingChildren() && (dx != 0 || dy != 0))
    { ... }
    if(bRedraw)
    { ... }

    use this:

    if (dx != 0 || dy != 0) {
    if(bRedraw) {
    pT->ScrollWindowEx(dx, dy,
    m_uScrollFlags|SW_ERASE|SW_INVALIDATE);
    } else {
    pT->ScrollWindowEx(dx, dy, m_uScrollFlags & ~
    (SW_ERASE|SW_INVALIDATE));
    }
    } else if (bRedraw) {
    pT->Invalidate();
    }

    The same for SetScrollSize (but you'll need to keep the
    SetScrollLine/SetScrollPage)

    And in the OnSize:
    instead of
    if(pT->AdjustScrollOffset(x, y))
    { ... }

    use this:

    if(pT->AdjustScrollOffset(x, y))
    {
    SetScrollOffset(x, y, TRUE);
    }

     
    • assigned_to: nobody --> nenadstefanovic