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.
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
|
|