CListCtrl只使用一列,大小改变时调整表头宽度占满客户区宽度,当窗口小有垂直滚动条且滚动条不是位于顶端时,最大化到没有垂直滚动条,顶部出现空行

WeroCPP 2019-04-15 11:29:18
CListCtrl以Report风格,去掉水平滚动条,垂直滚动条自适应,表头在OnSize中调整填满整个客户区宽度。
当控件窗口较小时出现垂直滚动条,此时把滚动条向下滚动使得垂直滚动条不是位于顶端,然后执行最大化,由于窗口变大,行数不足显示一页,此时变为没有垂直滚动条模式,结果发现顶端会出现空行,空行的数量是小窗口时顶端隐藏的行数。
如果始终显示垂直滚动条没有这个问题;
如果表头是LVSCW_AUTOSIZE按内容适配宽度也没有问题;
只有当表头是填满整个客户区宽度时会有问题。

谢谢!
...全文
527 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
WeroCPP 2021-08-06
  • 打赏
  • 举报
回复

多次遇到这个问题,终于绕路解决了,在OnSize中启动一个时钟,在时钟函数里调整列宽,把调整列宽变成异步的解决问题。

schlafenhamster 2019-04-23
  • 打赏
  • 举报
回复
14楼的代码 你试试 ,没 发现 问题
WeroCPP 2019-04-23
  • 打赏
  • 举报
回复
引用 19 楼 schlafenhamster 的回复:
14楼的代码 你试试 ,没 发现 问题

14楼代码只能实现15楼中的图1,图2是把表头占满整个客户区宽度就不行了。
零隐 2019-04-22
  • 打赏
  • 举报
回复
不设置列宽,也会出现这种情况?
WeroCPP 2019-04-22
  • 打赏
  • 举报
回复
引用 17 楼 fly0413 的回复:
不设置列宽,也会出现这种情况?

只要不要求表头占满整个客户区宽度,都不会有问题。
WeroCPP 2019-04-21
  • 打赏
  • 举报
回复
引用 15 楼 schlafenhamster 的回复:
init

// TODO: Add extra initialization here
m_ctrlList.InsertColumn(0, "", LVCFMT_LEFT, 1);
m_ctrlList.InsertColumn(1, "表头", LVCFMT_LEFT, 100);

CString strItem;
for (int i=0; i<7; i++)
{
strItem.Format("行行内容行内容行内容行内容行内容行内容行内容行内容行内容行内容行内容内容%d", i+1);
m_ctrlList.InsertItem(i, strItem);
m_ctrlList.SetItem(i, 1, LVIF_TEXT, strItem, 0, 0, 0, 0);
}
// 修改列宽
m_ctrlList.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);// -2



void CListCtrlDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if(IsWindow(m_ctrlList))
{
CRect rc;
GetClientRect(&rc);
// 修改列宽
m_ctrlList.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);// -2
m_ctrlList.MoveWindow(&rc);
m_ctrlList.ShowScrollBar(SB_HORZ, FALSE);// must after MoveWindow
}
// TODO: Add your message handler code here
}



这个表头没有填满整个客户区宽度是没有问题的,图片如下:



如果表头填满整个宽度,当窗口较小使得滚动条不是在顶端,然后最大化,顶端空行,图:



schlafenhamster 2019-04-20
  • 打赏
  • 举报
回复
init

// TODO: Add extra initialization here
m_ctrlList.InsertColumn(0, "", LVCFMT_LEFT, 1);
m_ctrlList.InsertColumn(1, "表头", LVCFMT_LEFT, 100);

CString strItem;
for (int i=0; i<7; i++)
{
strItem.Format("行行内容行内容行内容行内容行内容行内容行内容行内容行内容行内容行内容内容%d", i+1);
m_ctrlList.InsertItem(i, strItem);
m_ctrlList.SetItem(i, 1, LVIF_TEXT, strItem, 0, 0, 0, 0);
}
// 修改列宽
m_ctrlList.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);// -2



void CListCtrlDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if(IsWindow(m_ctrlList))
{
CRect rc;
GetClientRect(&rc);
// 修改列宽
m_ctrlList.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);// -2
m_ctrlList.MoveWindow(&rc);
m_ctrlList.ShowScrollBar(SB_HORZ, FALSE);// must after MoveWindow
}
// TODO: Add your message handler code here
}

schlafenhamster 2019-04-20
  • 打赏
  • 举报
回复
用 CListCtrl 没问题
零隐 2019-04-19
  • 打赏
  • 举报
回复
这不是没刷新吗。控件redraw 试一下看看。
不应该有空行,除非插入的时候就插入了空行。
zgl7903 2019-04-19
  • 打赏
  • 举报
回复

BOOL CDlg2Dlg::OnInitDialog()
{
  CDialog::OnInitDialog();

  // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
  //  执行此操作
  SetIcon(m_hIcon, TRUE);			// 设置大图标
  SetIcon(m_hIcon, FALSE);		// 设置小图标

  // TODO: 在此添加额外的初始化代码

  m_ListCtrl.InsertColumn(0, _T("Test"));
  m_ListCtrl.InsertItem(0, _T("12345612"));

  PostMessage(WM_SIZE, 0, 0);

  return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CDlg2Dlg::OnSize(UINT nType, int cx, int cy)
{
  CDialog::OnSize(nType, cx, cy);

  // TODO: 在此处添加消息处理程序代码

  if(m_ListCtrl.m_hWnd)
  {
    CRect rcRect;
    m_ListCtrl.GetClientRect(&rcRect);    
    m_ListCtrl.SetColumnWidth(0, rcRect.Width());
  }
}

WeroCPP 2019-04-19
  • 打赏
  • 举报
回复
引用 11 楼 zgl7903 的回复:
添加 WM_SZIE 响应, 在OnSize 中 根据窗口大小调整下列宽

就是自动调整列宽使得占满整个宽度才导致的问题。
zgl7903 2019-04-19
  • 打赏
  • 举报
回复
添加 WM_SZIE 响应, 在OnSize 中 根据窗口大小调整下列宽
零隐 2019-04-19
  • 打赏
  • 举报
回复
引用 9 楼 WeroCPP 的回复:
[quote=引用 8 楼 fly0413 的回复:]
这不是没刷新吗。控件redraw 试一下看看。
不应该有空行,除非插入的时候就插入了空行。

当存在滚动条且滚动条不是位于顶端,就是前面有被隐藏的行,比如此时被隐藏了3行,行高假设为20,第4行的顶端坐标应该为0,第1行的顶端坐标为-60。当变更到大尺寸垂直滚动条消失时,这时可以看到GetItemRect取得第一行的顶端位置为60,正好是之前没隐藏的3行的高度。感觉像是直接用0 -(-60)得到了第一行的位置。
[/quote]
看你 listctrl是自绘的还是用系统的?
我感觉我自绘不会出现这现象。或者说自绘的时候 onpaint 是不是刷新不到位。
一般放大缩小都是会保留之前视图的,类似它自己有刷新一下。
WeroCPP 2019-04-19
  • 打赏
  • 举报
回复
引用 8 楼 fly0413 的回复:
这不是没刷新吗。控件redraw 试一下看看。
不应该有空行,除非插入的时候就插入了空行。

当存在滚动条且滚动条不是位于顶端,就是前面有被隐藏的行,比如此时被隐藏了3行,行高假设为20,第4行的顶端坐标应该为0,第1行的顶端坐标为-60。当变更到大尺寸垂直滚动条消失时,这时可以看到GetItemRect取得第一行的顶端位置为60,正好是之前没隐藏的3行的高度。感觉像是直接用0 -(-60)得到了第一行的位置。
WeroCPP 2019-04-19
  • 打赏
  • 举报
回复
引用 6 楼 schlafenhamster 的回复:
是 CMFCListCtrl ?
改 CListCtrl 试试

都试过,现象是一样的,CFMCListCtrl派生自CListCtrl,感觉像是一个BUG。
schlafenhamster 2019-04-18
  • 打赏
  • 举报
回复
是 CMFCListCtrl ?
改 CListCtrl 试试
WeroCPP 2019-04-17
  • 打赏
  • 举报
回复
引用 4 楼 schlafenhamster 的回复:
我问 CListCtrl 是 怎么 填充 的 ?


最开始1列不行,后来修改成2列,第一列宽度设为0,依然不行。

m_ctrlList.InsertColumn(0, L" ", 0, 1);
m_ctrlList.InsertColumn(1, L"表头", 0, 100);

CString strItem;
for (int i=0; i<7; i++)
{
strItem.Format(L"行行内容行内容行内容行内容行内容行内容行内容行内容行内容行内容行内容内容%d", i+1);
m_ctrlList.InsertItem(i, strItem);
m_ctrlList.SetItem(i, 1, LVIF_TEXT, strItem, 0, 0, 0, 0);
}

void CListCtrlExtend::OnSize(UINT nType, int cx, int cy)
{
CMFCListCtrl::OnSize(nType, cx, cy);

// TODO: Add your message handler code here
// 自动调整列宽
if (GetHeaderCtrl().GetItemCount() > 0)
{
AutoAdjustColumnWidth();
}
}

// 调整列宽
void CListCtrlExtend::AutoAdjustColumnWidth(void)
{
// 窗口有效性
if (GetSafeHwnd() == NULL)
{
return;
}

CRect rcClient;
GetClientRect(&rcClient);

// 修改列宽
SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);//LVSCW_AUTOSIZE_USEHEADER//LVSCW_AUTOSIZE
}
schlafenhamster 2019-04-17
  • 打赏
  • 举报
回复
我问 CListCtrl 是 怎么 填充 的 ?
zgl7903 2019-04-16
  • 打赏
  • 举报
回复
WeroCPP 2019-04-16
  • 打赏
  • 举报
回复
引用 2 楼 schlafenhamster 的回复:
CListCtrl 是 怎么 Insert 的?

以MFC控件的方式添加的控件变量,您问的是这个吗?
加载更多回复(1)

15,978

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧