用图标计算 CComboBoxEx 的最大下拉宽度

Posted

技术标签:

【中文标题】用图标计算 CComboBoxEx 的最大下拉宽度【英文标题】:Working out the maximum drop-down width for a CComboBoxEx with icons 【发布时间】:2018-12-10 21:12:50 【问题描述】:

我在CodeProject 上看到了这篇关于动态设置CComboBox 的宽度的文章。

但是,我使用的是CComboBoxEx

正如您在最后一个条目中看到的那样,它被裁剪了。所以我想自动加宽下拉列表。

需要考虑到它们也是左侧图标的空间。所以这还不够好:

BOOL CMyComboBox::OnCbnDropdown()
 
    // Reset the dropped width
    CString str;
    CRect rect;
    int nWidth  = 0;
    int nNumEntries = GetCount();;

    CClientDC dc(this);

    int nSave = dc.SaveDC();
    dc.SelectObject(GetFont());

    for (int i = 0; i < nNumEntries; i++)
    
        GetLBText(i, str); 
        int nLength = dc.GetTextExtent(str).cx;
        if (nLength>nWidth)
            nWidth = nLength;
    

    nWidth += 2*::GetSystemMetrics(SM_CXEDGE) + 4;

    // check if the current height is large enough for the items in the list
    GetDroppedControlRect(&rect);
    if (rect.Height() <= nNumEntries*GetItemHeight(0))
        nWidth +=::GetSystemMetrics(SM_CXVSCROLL);


    dc.RestoreDC(nSave);
    SetDroppedWidth(nWidth);

    return FALSE;

我们如何考虑左侧的图标?

【问题讨论】:

您还应该考虑到COMBOBOXEXITEM::iIndent — docs.microsoft.com/en-us/windows/desktop/api/commctrl/… — “要为项目显示的缩进空间的数量。每个缩进等于 10 个像素。” @sergiol 这是一次性计算吗?我查看了链接,但不确定如何调整最终代码。我是否使用GetItem 来获取缩进和文本?也许您可以用附录更新我的答案? 出于完全相同的目的,我想知道同样的事情:***.com/questions/52428007/…。但iIndent 表示图标LEFT 处的间隔。它对于在下拉列表中分层组织项目很有用。 @sergiol 查看我的更新答案。 【参考方案1】:

这是有效的:

void CDatesComboBoxEx::OnCbnDropdown()

    CString str;
    CRect rect;
    int nWidth = 0, nImageWidth = 0;
    int nNumEntries = GetCount();

    if (nNumEntries > 0)
    
        // Get the width of an image list entry
        auto pImageList = GetImageList();
        if (pImageList != nullptr && pImageList->GetImageCount() > 0)
        
            IMAGEINFO sInfo;
            pImageList->GetImageInfo(0, &sInfo);
            nImageWidth = sInfo.rcImage.right - sInfo.rcImage.left;
        

        CClientDC dc(this);

        int nSave = dc.SaveDC();
        dc.SelectObject(GetFont());

        for (int i = 0; i < nNumEntries; i++)
        
            COMBOBOXEXITEM sItem;
            TCHAR szBuffer[_MAX_PATH] = _T("");
            sItem.mask = CBEIF_INDENT | CBEIF_TEXT;
            sItem.iItem = i;
            sItem.cchTextMax = _MAX_PATH;
            sItem.pszText = szBuffer;

            if (GetItem(&sItem))
            
                int nLength = dc.GetTextExtent(szBuffer).cx + nImageWidth + (sItem.iIndent * 10);
                if (nLength > nWidth)
                    nWidth = nLength;
            
        

        nWidth += 2 * ::GetSystemMetrics(SM_CXEDGE) + 4;

        // check if the current height is large enough for the items in the list
        GetDroppedControlRect(&rect);
        if (rect.Height() <= nNumEntries * GetItemHeight(0))
            nWidth += ::GetSystemMetrics(SM_CXVSCROLL);

        dc.RestoreDC(nSave);
        SetDroppedWidth(nWidth);
    

结果:

【讨论】:

以上是关于用图标计算 CComboBoxEx 的最大下拉宽度的主要内容,如果未能解决你的问题,请参考以下文章

CImageList 和 CComboBoxEx 限制为 16 个透明图标

如何设置 select2 下拉菜单的最小宽度和最大宽度?

Kendo UI 下拉列表采用最大选项的大小

QCombobox设置下拉框的宽度

设置剑道 ui 下拉列表宽度

设置表格中文本的最大宽度 td