列表框动态更改宽度 [英] Listbox change width dynamically

查看:163
本文介绍了列表框动态更改宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

列表框不会自动调整大小.我们拥有的最好的是:

Listboxes do not auto-resize. The best we've got is:

SendMessage(my_listbox, LB_SETHORIZONTALEXTENT, 1000, 0);

MS有帮助地指出"...列表框不会动态更新其水平范围."

MS helpfully notes that "...a list box does not update its horizontal extent dynamically."

(为什么不...但是我离题了)

如何动态设置宽度以避免截断超过1000像素的消息文本?

How can the width be set dynamically to avoid truncating the text of a message longer than 1000px?

推荐答案

如果我理解这个问题...:-)

if I understand the question... :-)

本质上,您需要测量列表框中的所有项目并计算列表框内容的最大宽度,然后调整列表框的宽度.

You'll essentially need to measure all of the items in the list box and calculate the maximum width of the list box contents, and then adjust the width of the listbox.

以下是此项目中的一些代码(向列表框添加了自动水平滚动条).字体更改时会调用此代码段,但它(大致)显示了所需的内容:

Here's some code from this project (that adds a automatic horizontal scrollbar to listboxes). This snippet is called when the font changes but it demonstrates (roughly) what's needed:

static void OnSetFont( HWND hwnd, HFONT hFont )
//
//  Font has changed!
//  We need to measure all of our items and reset the horizontal extent of the listbox
{
    CData *pData = reinterpret_cast< CData * >( ::GetProp( hwnd, g_pcszDataProperty ) );

    pData->m_hFont = hFont;

    //
    //  Set up a HDC...
    HDC hdc = GetDC( hwnd );
    HGDIOBJ hOld = SelectObject( hdc, pData->m_hFont );


    //
    //  Record the average width for use as our 'fudge factor' later.
    TEXTMETRIC tm;
    GetTextMetrics( hdc, &tm );
    pData->m_nAvergeCharWidth = tm.tmAveCharWidth;


    pData->m_nMaxWidth = 0;

    //
    //  This is used as our item buffer. Saves us from having to handle the reallocation
    //  for different string lengths
    CArray< TCHAR, TCHAR > arrBuffer;

    //
    //  Quick reference to make the code below read better
    CArray< int, int > &arrWidth = pData->m_arrItemWidth;

    //
    //  The main loop. Iterate over the items, get their text from the listbox and measure
    //  it using our friendly little helper function.
    const UINT uCount = arrWidth.GetSize();
    for( UINT u = 0; u < uCount; u++ )
    {
        const int nLength = ::SendMessage( hwnd, LB_GETTEXTLEN, u, 0 );
        arrBuffer.SetSize( nLength + 1 );
        ::SendMessage( hwnd, LB_GETTEXT, u, (WPARAM)arrBuffer.GetData() );


        const int nItemWidth = BaseMeasureItem( pData, hwnd, hdc, arrBuffer.GetData() );

        pData->m_arrItemWidth.SetAt( u, nItemWidth );
        if( nItemWidth > pData->m_nMaxWidth )
        {
            pData->m_nMaxWidth = nItemWidth;
        }
    }


    //
    //  Now, either set the horizontal extent or not, depending on whether we think we need it.
    if( pData->m_nMaxWidth > pData->m_nClientWidth )
    {
        ::SendMessage( hwnd, LB_SETHORIZONTALEXTENT, pData->m_nMaxWidth + pData->m_nAvergeCharWidth, 0 );
    }
    else
    {
        ::SendMessage( hwnd, LB_SETHORIZONTALEXTENT, 0, 0 );
    }

    //
    //  The usual release of resources.
    SelectObject( hdc, hOld );
    ReleaseDC( hwnd, hdc );
}

和...

static int BaseMeasureItem( CData *pData, HWND hwnd, HDC hdc, LPCTSTR pcszText )
//
//  Measure and item and adjust the horizontal extent accordingly.
//  Because the HDC is already set up we can just do it.
//  We return the width of the string so our caller can use it.
{
    SIZE size;
    ::GetTextExtentPoint32( hdc, pcszText, _tcslen( pcszText ), &size ); 

    if( size.cx > pData->m_nMaxWidth )
    {

        pData->m_nMaxWidth = size.cx;

        if( pData->m_nMaxWidth > pData->m_nClientWidth )
        {
            ::SendMessage( hwnd, LB_SETHORIZONTALEXTENT, pData->m_nMaxWidth + pData->m_nAvergeCharWidth, 0 );
        }

    }

    return size.cx;
}

这篇关于列表框动态更改宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆