【问题标题】:How to resize a Win32 listbox to fit its content?如何调整 Win32 列表框的大小以适合其内容?
【发布时间】:2020-06-13 05:43:34
【问题描述】:

是否有任何方法可以调整 Win32 列表框的大小以适应其内容(显示其所有内容的最小大小,不需要滚动条),无论何时其项目发生变化?

谢谢!

编辑:我需要调整列表框的宽度和高度。

【问题讨论】:

    标签: c++ winapi listbox autoresize


    【解决方案1】:

    您没有指定是否需要水平和垂直,但我假设不是。基本上,您需要获取项目数和项目高度并将它们相乘,然后添加控件边框的空间(除非控件是无边框的,否则您可能需要玩弄这个):

    void AutosizeListBox(HWND hWndLB)
    {
        int iItemHeight = SendMessage(hWndLB, LB_GETITEMHEIGHT, 0, 0);
        int iItemCount = SendMessage(hWndLB, LB_GETCOUNT, 0, 0);
    
        // calculate new desired client size
        RECT rc;
        GetClientRect(hWndLB, &rc);
        rc.bottom = rc.top + iItemHeight * iItemCount;
    
        // grow for borders
        rc.right += GetSystemMetrics(SM_CXEDGE) * 2;
        rc.bottom += GetSystemMetrics(SM_CXEDGE) * 2;
    
        // resize
        SetWindowPos(hWndLB, 0, 0, 0, rc.right, rc.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
    }
    

    如果您还想要水平调整大小,则需要在 DC 中选择正确的字体,然后使用 GetTextExtentPoint32 循环遍历所有项目以计算最大文本长度。

    编辑:添加了一个计算水平尺寸的版本。

    void AutosizeListBox(HWND hWndLB)
    {
        int iItemHeight = SendMessage(hWndLB, LB_GETITEMHEIGHT, 0, 0);
        int iItemCount = SendMessage(hWndLB, LB_GETCOUNT, 0, 0);
    
        // get a DC and set up the font
        HDC hDC = GetDC(hWndLB);
        HGDIOBJ hOldFont = SelectObject(hDC, (HGDIOBJ)SendMessage(hWndLB, WM_GETFONT, 0, 0));
    
        // calculate width of largest string
        int iItemWidth = 0;
        for (int i = 0; i < iItemCount; i++)
        {
            int iLen = SendMessage(hWndLB, LB_GETTEXTLEN, i, 0);
            TCHAR* pBuf = new TCHAR[iLen + 1];
            SendMessage(hWndLB, LB_GETTEXT, i, (LPARAM)pBuf);
    
            SIZE sz;
            GetTextExtentPoint32(hDC, pBuf, iLen, &sz);
            if (iItemWidth < sz.cx) iItemWidth = sz.cx;
    
            delete[] pBuf;
        }
    
        SelectObject(hDC, hOldFont);
        ReleaseDC(hWndLB, hDC);
    
        // calculate new desired client size
        RECT rc;
        SetRect(&rc, 0, 0, iItemWidth, iItemHeight * iItemCount);
    
        // grow for borders
        rc.right += GetSystemMetrics(SM_CXEDGE) * 2;
        rc.bottom += GetSystemMetrics(SM_CXEDGE) * 2;
    
        // resize
        SetWindowPos(hWndLB, 0, 0, 0, rc.right, rc.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
    }
    

    【讨论】:

    • 请注意,这仅适用于单列列表框;如果您使用的是您在其他问题中描述的多列列表框,那么方法会有所不同。
    • 确实,我需要两种尺寸,因为此列表框可用作文本框的工具提示选项。
    • @TuyenTk:你能确认单列还是多列?
    • 它是单列,所有项目都是纯文本。这不是自定义列表框
    • @TuyenTk:我已经编辑了我的答案,并举例说明了如何做到这一点。您可能需要尝试并添加一些额外的空间(我还没有实际测试过)。
    猜你喜欢
    • 1970-01-01
    • 2011-02-26
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-21
    • 1970-01-01
    相关资源
    最近更新 更多