当缩略图被正确重绘时,不会重绘滚动条箭头

时间:2011-06-03 01:21:09

标签: c++ winapi

我通过为它注册一个新类并将其作为子实例化到顶级窗口来创建自定义控件。该控件基本上是一个列表。为了省力,我决定使用WS_VSCROLL窗口类将滚动条添加到我的自定义控件。

我的麻烦在于,当我调整窗口大小时,我会重新计算缩略图的大小和页面大小等,然后调用SetScrollInfo并将重绘变量设置为true。这会正确地重绘拇指轨,但箭头不会重绘。因此,如果我从下面调整窗口大小the top arrow is still good,但是底部会丢失。如果我向右调整大小,则两个箭头都会改变位置and so both disappear

我似乎无法找到一种方法来获取WS_VSCROLL创建的内部滚动条控件的句柄,以便在其上调用invalidate。我真的不知道如何在这里进行表格。要记住的一件事是,如果我添加CS_VREDRAW | CS_HREDRAW到顶级窗口,一切都被正确绘制,所以我知道至少内部值都很好。就是这样,我得到了太多的重绘和闪烁。

编辑:我发布了一些代码。我真的很想避免这种情况,因为我可能会感到羞耻,但请知道可能除了我以外没有人会使用它。

该控件是一组推文,与Tweetdeck的工作方式类似。每条推文也是一个自定义控件,但画得很好,我没有问题。列控件本身根本不响应WM_PAINT,因为它只包含Tweet控件,它们处理自己的绘画。

以下是每个窗口类:

  • 顶级的注册类为NULL,CreateWindow类为WS_OVERLAPPED | WS_CLIPCHILDREN。
  • 列的寄存器类为NULL,CreateWindow类为WS_CHILD | WS_VSCROLL。
  • tweet的寄存器类为NULL,CreateWindow类为WS_CHILD。

代码:

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;
}

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);
}

2 个答案:

答案 0 :(得分:0)

在父类上实现滚动条,而不是您的子类。这将阻止重映到子类的消息导致子类完全重绘它自己。不要在父类上处理wm_paint消息,只能在子类中处理。这将允许Windows在滚动条上执行默认处理。两个窗口都需要CS_HREDRAW | CS_VREDRAW。

答案 1 :(得分:0)

您可以尝试向WM_SIZE处理程序中的列发送额外的WM_NCPAINT消息。但我认为这是自动发生的。

但我发现BrendanMcK提出的解决方案是使用默认列表框获胜者。可惜这不是答案。