【问题标题】:Listbox change width dynamically列表框动态改变宽度
【发布时间】:2012-11-20 16:25:21
【问题描述】:

列表框不会自动调整大小。我们得到的最好的结果是:

SendMessage(my_listbox, LB_SETHORIZONTALEXTENT, 1000, 0);

MS 有用地指出“...列表框不会动态更新其水平范围。”

(为什么不……但我离题了)

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

【问题讨论】:

    标签: c++ c winapi layout win32gui


    【解决方案1】:

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

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

    这里有一些来自this project 的代码(向列表框添加了一个自动水平滚动条)。当字体更改时会调用此 sn-p,但它(大致)演示了需要什么:

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

    【讨论】:

    • 你明白的,它看起来像。明天我会看看这个,我现在有点脑残。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-10-14
    • 2011-01-11
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    相关资源
    最近更新 更多