Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » behavior change in combo box Collapse All
Subject Author Date
Chris Anderson Jan 20, 2009 - 3:58 PM

I just found a behavior change in CExtComboBox class : if you insert a large number of items ( say 100 ) into a combo box, during run time, click the combo box, and press "Page Down", it always jump to the last item, while in MFC it only goes to the next "page".


Looks like this is done on purpose, see



void



CExtComboBoxPopupListBox::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )   {


...



 



case VK_END:

case VK_NEXT:


 



{


 


// Select last non-disabled item

INT nCurSel = pListBox->GetCurSel();


INT nCount = pListBox->GetCount();


INT nSel = nCount;


any reason behind this ? thanks


Technical Support Jan 22, 2009 - 12:35 PM

Thank you for reporting this issue. To fix it, please update the source code for the CExtComboBoxPopupListBox::OnKeyDown() method:

void CExtComboBoxPopupListBox::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags ) 
{
            ASSERT_VALID( this );
            if( m_pCB->GetDroppedState() )
            {
                        DWORD dwComboBoxType = m_pCB->GetStyle() & 0x0003L;
                        CListBox * pListBox = ( CListBox * ) this;
                        bool bSelChanged = false;
                        switch( nChar )
                        {
                                    case VK_LEFT:
                                    case VK_UP:
                                    {
                                                INT nCount = pListBox->GetCount();
                                                if( nCount == 0 )
                                                            break;
                                                // Go up until we find a valid selection then set the current selection to that one
                                                INT nCurSel = pListBox->GetCurSel();
                                                INT nSel = nCurSel;
                                                bool bInitSelection = false;
                                                if(         nSel < 0 && nCount > 0 )
                                                {
                                                            nSel = nCount - 1;
                                                            bInitSelection = true;
                                                }
                                                if( nSel != LB_ERR )
                                                {
                                                            while( nSel > 0 )
                                                            {
                                                                        INT nItem = nSel - ( bInitSelection ? 0 : 1 );
                                                                        if( m_pCB->LbItemIsEnabled( nItem ) )
                                                                        {
                                                                                    if( nCurSel != nItem )
                                                                                    {
                                                                                                pListBox->SetRedraw( FALSE );
                                                                                                INT nRealSel = pListBox->SetCurSel( nItem );
                                                                                                if( nCurSel != nRealSel )
                                                                                                {
                                                                                                            if( dwComboBoxType == CBS_DROPDOWNLIST )
                                                                                                            {
                                                                                                                        INT nTopIndex = pListBox->GetTopIndex();
                                                                                                                        m_pCB->SetCurSel( nRealSel );
                                                                                                                        pListBox->SetTopIndex( nTopIndex );
                                                                                                            }
                                                                                                            else
                                                                                                            {
                                                                                                                        CString sText;
                                                                                                                        pListBox->GetText( nRealSel, sText );
                                                                                                                        m_pCB->SetWindowText( sText );
                                                                                                                        m_pCB->SetEditSel( 0, -1 );
                                                                                                            }
                                                                                                            bSelChanged = true;
                                                                                                }
                                                                                                pListBox->SetRedraw( TRUE );
                                                                                                pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
                                                                                    }
                                                                                    break;
                                                                        }
                                                                        nSel--;
                                                            }
                                                }
                                    }
                                    break;
                                    case VK_RIGHT:
                                    case VK_DOWN:
                                    {
                                                INT nCount = pListBox->GetCount();
                                                if( nCount == 0 )
                                                            break;
                                                // Go down until we find a valid selection then set the current selection to that one
                                                INT nCurSel = pListBox->GetCurSel();
                                                INT nSel = nCurSel;
                                                bool bInitSelection = false;
                                                if(         nSel < 0 && nCount > 0 )
                                                {
                                                            nSel = 0;
                                                            bInitSelection = true;
                                                }
                                                if( nSel != LB_ERR )
                                                {
                                                            while( nSel < nCount - 1 )
                                                            {
                                                                        INT nItem = nSel + ( bInitSelection ? 0 : 1 );
                                                                        if( nItem == nCount )
                                                                                    break;
                                                                        if( m_pCB->LbItemIsEnabled( nItem ) )
                                                                        {
                                                                                    if( nCurSel != nItem )
                                                                                    {
                                                                                                pListBox->SetRedraw( FALSE );
                                                                                                INT nRealSel = pListBox->SetCurSel( nItem );
                                                                                                if( nCurSel != nRealSel )
                                                                                                {
                                                                                                            if( dwComboBoxType == CBS_DROPDOWNLIST )
                                                                                                            {
                                                                                                                        INT nTopIndex = pListBox->GetTopIndex();
                                                                                                                        m_pCB->SetCurSel( nRealSel );
                                                                                                                        pListBox->SetTopIndex( nTopIndex );
                                                                                                            }
                                                                                                            else
                                                                                                            {
                                                                                                                        CString sText;
                                                                                                                        pListBox->GetText( nRealSel, sText );
                                                                                                                        m_pCB->SetWindowText( sText );
                                                                                                                        m_pCB->SetEditSel( 0, -1 );
                                                                                                            }
                                                                                                            bSelChanged = true;
                                                                                                }
                                                                                                pListBox->SetRedraw( TRUE );
                                                                                                pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
                                                                                    }
                                                                                    break;
                                                                        }
                                                                        nSel++;
                                                            }
                                                }
                                    }
                                    break;
                                    case VK_PRIOR:
                                    {
                                                INT nCount = pListBox->GetCount();
                                                if( nCount == 0 )
                                                            break;
                                                INT nTopIndex = pListBox->GetTopIndex();
                                                INT nCurSel = pListBox->GetCurSel();
                                                if( nCurSel == 0 && nTopIndex == 0 )
                                                            break;
                                                SCROLLINFO _scroll_info;
                                                ::memset( &_scroll_info, 0, sizeof(SCROLLINFO) );
                                                _scroll_info.cbSize = sizeof(SCROLLINFO);
                                                if(         ! pListBox->GetScrollInfo( SB_VERT, &_scroll_info ) )
                                                            break;
                                                INT nNewSel = _scroll_info.nPos - _scroll_info.nPage;
                                                if( nNewSel < 0 )
                                                            nNewSel = 0;
                                                if( nNewSel != nCurSel || nTopIndex != nNewSel  )
                                                {
                                                            pListBox->SetRedraw( FALSE );
                                                            if( nTopIndex != nNewSel )
                                                                        pListBox->SetTopIndex( nNewSel );
                                                            if( nNewSel != nCurSel )
                                                            {
                                                                        m_pCB->SetCurSel( nNewSel );
                                                                        bSelChanged = true;
                                                            }
                                                            if( dwComboBoxType != CBS_DROPDOWNLIST )
                                                            {
                                                                        CString sText;
                                                                        pListBox->GetText( nNewSel, sText );
                                                                        m_pCB->SetWindowText( sText );
                                                                        m_pCB->SetEditSel( 0, -1 );
                                                            }
                                                            pListBox->SetRedraw( TRUE );
                                                            pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
                                                }
                                    }
                                    break;
                                    case VK_NEXT:
                                    {
                                                INT nCount = pListBox->GetCount();
                                                if( nCount == 0 )
                                                            break;
                                                INT nTopIndex = pListBox->GetTopIndex();
                                                INT nCurSel = pListBox->GetCurSel();
                                                SCROLLINFO _scroll_info;
                                                ::memset( &_scroll_info, 0, sizeof(SCROLLINFO) );
                                                _scroll_info.cbSize = sizeof(SCROLLINFO);
                                                if(         ! pListBox->GetScrollInfo( SB_VERT, &_scroll_info ) )
                                                            break;
                                                INT nNewTopIndex = _scroll_info.nPos + _scroll_info.nPage;
                                                INT nNewSel = nNewTopIndex + _scroll_info.nPage - 1;
                                                if( nNewSel >= nCount )
                                                            nNewSel = nCount - 1;
                                                if( nNewSel != nCurSel || nNewTopIndex != nTopIndex )
                                                {
                                                            pListBox->SetRedraw( FALSE );
                                                            if( nNewSel != nCurSel )
                                                            {
                                                                        m_pCB->SetCurSel( nNewSel );
                                                                        bSelChanged = true;
                                                            }
                                                            if( nNewTopIndex != nTopIndex )
                                                                        m_pCB->SetTopIndex( nNewTopIndex );
                                                            if( dwComboBoxType != CBS_DROPDOWNLIST )
                                                            {
                                                                        CString sText;
                                                                        pListBox->GetText( nNewSel, sText );
                                                                        m_pCB->SetWindowText( sText );
                                                                        m_pCB->SetEditSel( 0, -1 );
                                                            }
                                                            pListBox->SetRedraw( TRUE );
                                                            pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
                                                }
                                    }
                                    break;
                                    case VK_HOME:
                                    {
                                                INT nCount = pListBox->GetCount();
                                                if( nCount == 0 )
                                                            break;
                                                // Select first non-disabled item
                                                INT nCurSel = pListBox->GetCurSel();
                                                INT nSel = 0;
                                                while( nSel < nCount - 1 )
                                                {
                                                            INT nItem = nSel;
                                                            if( m_pCB->LbItemIsEnabled( nItem ) )
                                                            {
                                                                        if( nCurSel != nItem )
                                                                        {
                                                                                    pListBox->SetRedraw( FALSE );
                                                                                    INT nRealSel = pListBox->SetCurSel( nItem );
                                                                                    if( nCurSel != nRealSel )
                                                                                    {
                                                                                                if( dwComboBoxType == CBS_DROPDOWNLIST )
                                                                                                {
                                                                                                            INT nTopIndex = pListBox->GetTopIndex();
                                                                                                            m_pCB->SetCurSel( nRealSel );
                                                                                                            pListBox->SetTopIndex( nTopIndex );
                                                                                                }
                                                                                                else
                                                                                                {
                                                                                                            CString sText;
                                                                                                            pListBox->GetText( nRealSel, sText );
                                                                                                            m_pCB->SetWindowText( sText );
                                                                                                            m_pCB->SetEditSel( 0, -1 );
                                                                                                }
                                                                                                bSelChanged = true;
                                                                                    }
                                                                                    pListBox->SetRedraw( TRUE );
                                                                                    pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
                                                                        }
                                                                        break;
                                                            }
                                                            nSel++;
                                                }
                                    }
                                    break;
                                    case VK_END:
                                    {
                                                INT nCount = pListBox->GetCount();
                                                if( nCount == 0 )
                                                            break;
                                                // Select last non-disabled item
                                                INT nCurSel = pListBox->GetCurSel();
                                                INT nSel = nCount;
                                                while( nSel > 0 )
                                                {
                                                            INT nItem = nSel - 1;
                                                            if( m_pCB->LbItemIsEnabled( nItem ) )
                                                            {
                                                                        if( nCurSel != nItem )
                                                                        {
                                                                                    pListBox->SetRedraw( FALSE );
                                                                                    INT nRealSel = pListBox->SetCurSel( nItem );
                                                                                    if( nCurSel != nRealSel )
                                                                                    {
                                                                                                if( dwComboBoxType == CBS_DROPDOWNLIST )
                                                                                                {
                                                                                                            INT nTopIndex = pListBox->GetTopIndex();
                                                                                                            m_pCB->SetCurSel( nRealSel );
                                                                                                            pListBox->SetTopIndex( nTopIndex );
                                                                                                }
                                                                                                else
                                                                                                {
                                                                                                            CString sText;
                                                                                                            pListBox->GetText( nRealSel, sText );
                                                                                                            m_pCB->SetWindowText( sText );
                                                                                                            m_pCB->SetEditSel( 0, -1 );
                                                                                                }
                                                                                                bSelChanged = true;
                                                                                    }
                                                                                    pListBox->SetRedraw( TRUE );
                                                                                    pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
                                                                        }
                                                                        break;
                                                            }
                                                            nSel--;
                                                }
                                    }
                                    break;
                        default:
                                    CWnd::OnKeyDown( nChar, nRepCnt, nFlags );
                        return;
                        } // switch( nChar )
                        if( bSelChanged )
                        {
                                    // The CBN_SELCHANGE notification message is not sent when the selection 
                                    // is changed using the CB_SETCURSEL message. 
                                    if( ! m_pCB->m_bEnableSelChangeWorkaround  )
                                    {
                                                CWnd * pWnd = m_pCB->GetParent();
                                                if( pWnd->GetSafeHwnd() != NULL )
                                                {
                                                            ASSERT_VALID( pWnd );
                                                            pWnd->SendMessage(
                                                                        WM_COMMAND,
                                                                        MAKEWPARAM( m_pCB->GetDlgCtrlID(), CBN_SELCHANGE ),
                                                                        (LPARAM) m_hWnd
                                                                        );
                                                }
                                    }
                        }
                        return;
            } // if( m_pCB->GetDroppedState() )
            CWnd::OnKeyDown( nChar, nRepCnt, nFlags );
}

Chris Anderson Jan 22, 2009 - 2:33 PM

thanks for your help, will try this out