【问题标题】:How to get width of list control in MFC application in pixels?如何在 MFC 应用程序中获取列表控件的宽度(以像素为单位)?
【发布时间】:2020-12-26 12:08:44
【问题描述】:

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

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

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

最大化窗口后:

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

我尝试过的:

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 后,最大化对话框后的列表如下所示:

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

void CEditableListControlDlg::OnSize(UINT nType, int cx, 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 cx, 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

谢谢。

【问题讨论】:

    标签: c++ visual-studio mfc dialog


    【解决方案1】:

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

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

    您在帖子中提到的 SetColumnWidth 函数链接中也有引用。

    【讨论】:

    • 感谢您的评论。我想这就是我在方法1中尝试过的。问题是最后一列太大了,如下图所示方法1的描述。也许你知道我该如何解决它?
    【解决方案2】:

    您可以参考以下代码。也许它可以帮助你。

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

    【讨论】:

    • 感谢您的回答。我试过运行这段代码(我已经删除了int n = m_acclist-&gt;GetColumnWidth();这一行,因为如果不将参数传递给GetColumnWidth,它将无法工作,而且我不确定n的用途是什么)但我仍然得到相同的结果作为方法1:\在最大化对话框之后,是否有检索列表控件矩形的新宽度,然后将其除以列数?
    • 我建议你可以试试 Damir Valiulin 的方法,通过重新分配列的宽度来实现每列的宽度相同。
    【解决方案3】:

    因为LVSCW_AUTOSIZE_USEHEADER 会将最后一列的大小调整为剩余宽度,所以它对您没有帮助,因为您希望将总宽度均匀分布在所有列中。

    与您的方法 2 类似,您可以尝试以下方法:

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

    【讨论】:

      猜你喜欢
      • 2013-01-31
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      相关资源
      最近更新 更多