开发者

Scrollbar arrows do not get redrawn while thumbtrack gets redrawn correctly

I have created a custom control by registering a new class for it and instantiating it as a child to a top-level window. The control is basically a list. In order to save some effort, I decided to use the WS_VSCROLL window class in order to add scrollbars to my custom control.

My trouble is that when I resize the window, I proceed to recalculate the size of the thumbtrack and page size, etc. then call SetScrollInfo with the redraw variable set to true. This redraws the thumbtrack correctly, but the arrows do not get redrawn. Therefore, if I resize the window from below, the top arrow is still good, but the bottom one goes missing. If I resize to the right, then both arrows change position and so both disappear.

I can't seem to find a way to get a handle to the internal scrollbar control that WS_VSCROLL creates in order to call an invalidate on it or something. I really don't know how to proceed form here. One thing to keep in mind is that if I add CS_VREDRAW | CS_HREDRAW to the top level window, everything gets drawn correctly, so I know that at least the internal values are all fine. It's just that that way I get too much redrawing and flicker.

EDIT: I'm posting some code. I really wanted to avoid this because I'll probably be put to shame, but please know that probably no one but myself will ever use it.

The control is a column of tweets similar to how Tweetdeck works. Each tweet is also a custom control, but that paints just fine and I have no problems there. The column control itself does not respond to WM_PAINT at all because it just contains Tweet controls, which handle their own painting.

Here are also the window classes for each of these:

  • register class of top level is NULL and CreateWin开发者_JAVA技巧dow class is WS_OVERLAPPED | WS_CLIPCHILDREN.
  • register class of column is NULL and CreateWindow class is WS_CHILD | WS_VSCROLL.
  • register class of tweet is NULL and CreateWindow class is WS_CHILD.

Code:

LRESULT Column::OnResize(WPARAM wParam, LPARAM lParam) // responds to WM_SIZE
{
    // global height var
    lastWidth = width;
    lastHeight = height;
    width = LOWORD(lParam);
    height = HIWORD(lParam);
    //updateScrollPageSize();

    SCROLLINFO si;
    si.cbSize = sizeof(si);
    si.fMask  = SIF_ALL;
    GetScrollInfo (hWnd, SB_VERT, &si);

    // Resize all child tweets
    if (lastWidth != width ||
        lastHeight != height && si.nMax - si.nPos < height)
    {
        // C++0x lambdas can only take in local variables?!
        int localWidth = width;
        int *tweetBottomPtr = &lastTweetBottom;
        *tweetBottomPtr = 0;
        std::for_each(tweets.begin(), tweets.end(),
                      [localWidth, tweetBottomPtr, &si](TweetBox *tweet)
        {
            MoveWindow(tweet->getHandle(),
                       tweet->getX(), *tweetBottomPtr - si.nPos,
                       localWidth, tweet->getHeight(), TRUE);
            *tweetBottomPtr += tweet->getHeight();
        });
    }

    updateScrollPageSize();
    UpdateWindow(hWnd);

    return 0;
}

and

void Column::updateScrollPageSize()
{
    SCROLLINFO si;
    // Set the vertical scrolling range and page size
    si.cbSize = sizeof(si);
    si.fMask  = SIF_ALL;
    GetScrollInfo (hWnd, SB_VERT, &si);

    si.fMask  = SIF_PAGE | SIF_RANGE;
    si.nMin = 0;
    si.nMax = lastTweetBottom;
    si.nPage  = (int)((float)height / lastTweetBottom * si.nMax);
    SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
}


You could try sending an extra WM_NCPAINT message to the column in your WM_SIZE handler. But I thought that happens automatically.

But I find the solution proposed by BrendanMcK to make use of a default listbox the winner. Pity it's not an answer.


Implement your scroll bars on your parent class, Not your child class. This will prevent repaint messages to the child class from causing the child class to completely redraw it's self. Don't handle wm_paint messages on your parent class, only in your child class. This will allow windows to do default processing on the scroll bar. And both windows need to be CS_HREDRAW | CS_VREDRAW.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜