如何在MFC应用程序中以像素为单位获取列表控件的宽度?

问题描述

我正在用C ++在Visual Studio 2017上编写基于对话框的MFC应用程序。

我为用户添加了一个最大化/最小化窗口的选项。当用户调整对话框的大小时,我要调整控件的大小。在该应用程序中,有一个列表控件,如下图所示,该控件可调整为新的窗口大小。

最大化窗口之前-将每列的宽度调整为列表宽度:

enter image description here

最大化窗口后:

enter image description here

我的问题是我无法将其列调整为新的大小。我已经看到了有关该主题的一些帖子,但不幸的是我仍然无法解决问题。我希望这些列的大小大致相同并填充整个窗口。

我尝试过的方法:

1。方法1 -问题是最后一列比其他列大

void CEditableListControlDlg::OnSize(UINT nType,int cx,int cy) {

    if (m_bUseWMSize) {
        
        // adjust column width to window
        for (int i = 0; i < m_EditableList.GetHeaderCtrl()->GetItemCount(); ++i) {
            m_EditableList.SetColumnWidth(i,LVSCW_AUTOSIZE_USEHEADER);
        }
    }
    m_bUseWMSize = true;

}

变量m_bUseWMSize可以忽略-它只是一个标志,因此在创建对话框时我不会执行代码。我也尝试过将SetColumnWidth中的标志LVSCW_AUTOSIZE_USEHEADER切换为LVSCW_AUTOSIZE,但这也无济于事。

使用方法1后,最大化对话框后,列表如下所示:

enter image description here

2。方法2 -问题是列宽没有受到影响。我认为这是因为width变量的值为2147483647,即使我将其除以11(列数),它仍然太大

void CEditableListControlDlg::OnSize(UINT nType,int cy) {

    if (m_bUseWMSize) {
        RECT rect;
        m_EditableList.GetViewRect(&rect);
        int width = abs(rect.left - rect.right);
        int nCol = 11;
        // adjust column width to window
        for (int i = 0; i < m_EditableList.GetHeaderCtrl()->GetItemCount(); ++i) {
            m_EditableList.SetColumnWidth(i,width/nCol);
        }
    }
    m_bUseWMSize = true;

}

3。方法3 -我尝试以像素为单位检索列表的宽度,然后将其除以列数。问题是列宽太小,因为size.cx的值为512

void CEditableListControlDlg::OnSize(UINT nType,int cy) {

    if (m_bUseWMSize) {
        CSize cz;
        CSize size = m_EditableList.ApproximateViewRect(cz,-1);
        int nCol = 11;
        
        // adjust column width to window
        for (int i = 0; i < m_EditableList.GetHeaderCtrl()->GetItemCount(); ++i) {
            m_EditableList.SetColumnWidth(i,size.cx/11);
        }
    }
    m_bUseWMSize = true;

}

相关文档:

  1. SetColumnWidth Function
  2. RECT struct
  3. CSize struct
  4. Functions ApproximateViewRect and GetViewRect

谢谢。

解决方法

简单的选择是让控件为您完成:-)。根据以下文档主题,在向控件发送LVM_SETCOLUMNWIDTH消息时,可以传递一个特殊值(LVSCW_AUTOSIZE_USEHEADER):

https://docs.microsoft.com/en-us/windows/win32/controls/lvm-setcolumnwidth

您在帖子中提到的SetColumnWidth函数链接中也引用了该内容。

,

您可以参考以下代码。也许可以帮到您。

bool CMFCApplication4Dlg::AdjustColumnWidth(CListCtrl* m_acclist)       
    {
        CHeaderCtrl* pHeaderCtrl = m_acclist->GetHeaderCtrl();
        int n = m_acclist->GetColumnWidth();
        int nColumnCount = pHeaderCtrl->GetItemCount();             
        for (int i = 0; i < nColumnCount; i++)
        {
            m_acclist->SetColumnWidth(i,LVSCW_AUTOSIZE);
            int nColumnWidth = m_acclist->GetColumnWidth(i);        
            m_acclist->SetColumnWidth(i,LVSCW_AUTOSIZE_USEHEADER); 
            int nHeaderWidth = m_acclist->GetColumnWidth(i);
            m_acclist->SetColumnWidth(i,nColumnWidth > nHeaderWidth ? nColumnWidth : nHeaderWidth); 
        }
        return true;
    }
,

由于LVSCW_AUTOSIZE_USEHEADER会将最后一列的大小调整为剩余宽度,因此对您没有帮助,因为您希望在所有列上平均分配总宽度。

类似于方法2,您可以尝试以下操作:

  1. 对于每一列,包括标题在内的所有行都进行循环,并使用CListCtrl::GetStringWidth获取以像素为单位的文本宽度。存储每列的最大宽度
  2. 总结所有这些最大宽度
  3. 使用GetClientRect获取控制客户端矩形的宽度。如果存在滚动条,请用::GetSystemMetrics (SM_CXVSCROLL)
  4. 减去它
  5. 从3中减去2的结果并除以列数。将结果加到在1
  6. 中获得的每个最大宽度
  7. 使用SetColumnWidth为每一列分配新宽度

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...