C++ 当thumbtrack被正确重绘时,滚动条箭头不会被重绘

C++ 当thumbtrack被正确重绘时,滚动条箭头不会被重绘,c++,winapi,C++,Winapi,我已经创建了一个自定义控件,为它注册了一个新类,并将其实例化为顶级窗口的子控件。控件基本上是一个列表。为了节省一些工作量,我决定使用WS_VSCROLL窗口类向自定义控件添加滚动条 我的问题是,当我调整窗口大小时,我会继续重新计算thumbtrack的大小和页面大小等。然后调用SetScrolInfo,并将redraw变量设置为true。这将正确地重新绘制拇指轨迹,但不会重新绘制箭头。因此,如果我从下面调整窗口的大小,但底部的窗口将丢失。如果向右调整大小,则两个箭头都会改变位置 我似乎找不到一种

我已经创建了一个自定义控件,为它注册了一个新类,并将其实例化为顶级窗口的子控件。控件基本上是一个列表。为了节省一些工作量,我决定使用WS_VSCROLL窗口类向自定义控件添加滚动条

我的问题是,当我调整窗口大小时,我会继续重新计算thumbtrack的大小和页面大小等。然后调用SetScrolInfo,并将redraw变量设置为true。这将正确地重新绘制拇指轨迹,但不会重新绘制箭头。因此,如果我从下面调整窗口的大小,但底部的窗口将丢失。如果向右调整大小,则两个箭头都会改变位置

我似乎找不到一种方法来获取WS_VSCROLL创建的内部滚动条控件的句柄,以便对其调用invalidate之类的东西。我真的不知道如何从这里开始。需要记住的一点是,如果我将CS|u VREDRAW | CS|u HREDRAW添加到顶层窗口,所有内容都会正确绘制,因此我知道至少内部值都是正确的。就是这样,我得到了太多的重画和闪烁

编辑:我正在发布一些代码。我真的想避免这样做,因为我可能会感到羞愧,但请知道,除了我自己,可能没有人会使用它

控件是一列类似于Tweetdeck工作方式的tweet。每个tweet都是一个自定义控件,但这很好,我在那里没有问题。列控件本身根本不响应WM_PAINT,因为它只包含处理自己绘制的Tweet控件

以下是这些窗口的窗口类:

顶级的register类为NULL,CreateWindow类为WS|U OVERLAPPED | WS|U CLIPCHILDREN。 列的寄存器类为NULL,CreateWindow类为WS|u CHILD | WS|u VSCROLL。 tweet的register类为NULL,CreateWindow类为WS\u CHILD。 代码:


在父类而不是子类上实现滚动条。这将防止对子类重新绘制消息导致子类完全重新绘制其自身。不要在父类上处理wm_paint消息,只在子类中处理。这将允许windows在滚动条上执行默认处理。两个窗口都需要是CS_HREDRAW | CS_VREDRAW。

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


但我发现BrendanMcK提出的解决方案是使用默认列表框作为赢家。遗憾的是,这不是答案。

您的滚动条是在子窗口还是在父窗口上实现的?在子窗口上,是我的自定义类。您使用什么来绘制类,D2D,GDI,GDI+,DirectX什么?我用GDI画了一点点,我的控件使用了其他标准控件作为子控件,比如富编辑框。这里发生了一些奇怪的事情。。。滚动条是所谓的非客户端区域控件-它们与主窗口共享同一个句柄,这就是为什么没有内部句柄的原因,Windows应该负责绘制它们。这有点类似于Windows在顶级Windows上管理标题栏或菜单的方式。CS_H/VREDRAW在这里不应该有什么区别,他们决定当大小改变时整个客户端区域是否应该无效,但不应该影响非客户端区域的绘制方式。你能发布创建、调整和绘制窗口的代码吗?我不知道如何在父类上实现滚动条。我的子控件没有填满整个窗口,窗口中有几个,因此它必须有自己的滚动条。你的意思是我应该在顶层创建一个类SCROLLBAR控件并从那里处理子类的滚动吗?那好像是自找麻烦。我对孩子的控制应该是自给自足的。我也没有在父窗口上处理WM_PAINT。不,在另一个窗口中宿主实际的绘图窗口,并将其子类化为宿主控件的父窗口,但考虑到您不使用Direct 2D,这可能是不必要的。您在registerwindowclass上使用的样式是什么,还有createwindowex?我在我的原始帖子中添加了更多的信息。
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);
}