如何停止显示 CListCtrl 的底部滚动条?

Posted

技术标签:

【中文标题】如何停止显示 CListCtrl 的底部滚动条?【英文标题】:How to stop the bottom scrollbar from a CListCtrl from displaying? 【发布时间】:2018-02-21 00:33:01 【问题描述】:

我有一个CListCtrl,它会随着对话动态调整大小。我在派生的CListCtrl 中使用了WM_SIZE 消息处理程序来调整列的大小,使总和为控件的宽度 - 4,其中 - 4 表示边框的宽度。

当我使对话变大时,控件会正确调整大小并且我没有得到底部滚动条。但是,当我缩小控件时,有时会出现水平滚动条。

void CMyListCtrl::OnSize(UINT nType, int cx, int cy)

    CListCtrl::OnSize(nType, cx, cy);
    ResizeLastColumn();


void CMyListCtrl::ResizeLastColumn()

    LVCOLUMN column;
    column.mask = LVCF_WIDTH;
    LONG maxWidth = 0;
    for (int i = 0; i < lastColumnIndex; ++i)
    
        GetColumn(i, &column);
        maxWidth += column.cx;
    
    CRect wndRect;
    GetWindowRect(&wndRect);

    SetColumnWidth(lastColumnIndex, wndRect.Width() - maxWidth - 4);

就像WM_SIZE 消息在控件最终调整大小之前到达控件。

这与How to determine if a scrollbar for a CListCtrl is displaying? 有关。但是,这个问题不是在处理右滚动条,而是假设它没有被显示。

【问题讨论】:

【参考方案1】:

调整窗口大小会生成一条消息以测试水平滚动。 SetColumnWidth 也将生成相同的消息。这取决于 ListView 如何在内部处理此问题,但垂直滚动也可能进出,这将改变客户区,因此代码可能必须进行递归调用以确定滚动是否可见。您可以看到这很容易遇到问题。

在调用默认过程之前尝试调整WM_WINDOWPOSCHANGED 中的列大小。使用SetRedraw 停止多余的绘制消息。

ON_WM_WINDOWPOSCHANGED()
...
void CMyListCtrl::OnWindowPosChanged(WINDOWPOS *wpos)

    SetRedraw(FALSE);
    ResizeLastColumn();
    SetRedraw(TRUE);
    CListCtrl::OnWindowPosChanged(wpos);

客户区可以使用GetClientRect,这样就不需要减去边框粗细(不总是4)。

void ResizeLastColumn()

    int maxwidth = 0;
    int index = GetHeaderCtrl()->GetItemCount() - 1;
    for(int i = 0; i < index; ++i)
        maxwidth += GetColumnWidth(i);
    CRect rc;
    GetClientRect(&rc);
    SetColumnWidth(index, rc.Width() - maxwidth);

同样GetHeaderCtrl()-&gt;GetItemCount() 返回列数。

【讨论】:

哦。这听起来很有希望。 工作得很好。也使我的其他链接问题没有实际意义。 我试过OnWindowPosChanged 并且它工作正常,它似乎也适用于您的系统。但现在有时它不起作用!我使用SetRedraw 添加了第二种方法,该方法在 Windows 10 上始终有效。稍后我将在 Win7 上尝试。 啊,我只是将CListCtrl::OnWindowPosChanged(wpos) 放在末尾而不是开头,这很好,就像在您更新的代码中一样。 我发现一个奇怪的行为,我不知道它是否相关,如果我插入足够多的行以至于它溢出客户区,并且我使控件更高,它会隐藏所有行,直到我使它足够小以显示垂直滚动条并移动它。之后,它工作正常。也许与不关闭和重绘有关?【参考方案2】:

我面临完全相同的问题,使用完全相同的用例。

要完全禁用水平滚动条,请为 WM_NCCALCSIZE 添加消息处理程序

使用类向导将以下内容添加到您的消息映射中:

ON_WM_NCCALCSIZE()

在此处理程序的实现中,您修改样式以禁用水平滚动条。

void CMyListCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)

    ModifyStyle(WS_HSCROLL, 0); // disable the horizontal scroll bar

    __super::OnNcCalcSize(bCalcValidRects, lpncsp);

在我自己的 ResizeLastColumn() 实现中,与您的类似,我从宽度中减去 ::GetSystemMetrics(SM_CXVSCROLL) 以考虑垂直滚动条。

我知道这个回复有点晚了,但希望它会对某人有所帮助。

(已编辑以删除我遇到的一些问题的提及,因为 a)它们是题外话,b)因为我认为它们源于我没有使用 Doc-View 架构,因此事情没有正确连接。我会重新考虑我的方法。)

【讨论】:

以上是关于如何停止显示 CListCtrl 的底部滚动条?的主要内容,如果未能解决你的问题,请参考以下文章

如何停止 UITableView 在顶部和底部的滚动?

如何在CListCtrl中捕获滚动事件?

在顶部和底部停止滚动UITableView?

如何判断滚动条滚到页面底部并执行事件

请问,UEditor数据加载后,如何设置滚动条显示到顶部,而不是显示在底部

解决CListCtrl闪烁及水平滚动条不能跟踪拖动的问题(MFC)