📄 advcombobox.cpp
字号:
int nPos = pListBox->GetCurSel();
int nCount = pListBox->GetCount();
int nMaxVisible = pListBox->GetMaxVisibleItems();
int nTop = pListBox->GetTopIndex();
if (nPos <= 0)
return;
if (nPos == LB_ERR) // no selection
nPos = nCount - 1;
else if (nPos == 0) // top of list
/*nPos = -1*/;
else if (nPos == nTop) // at top of listbox window
{
nPos = nTop - nMaxVisible + 1; // this might be = -1
if (nPos < 0)
nPos = 0;
}
else // middle of listbox window
nPos = nTop;
pListBox->SetCurSel(nPos);
int nSel = pListBox->GetCurSel();
if (nSel == LB_ERR)
{
}
else
{
CString str = _T("");
pListBox->GetText(nSel, str);
SetWindowText(str);
}
}
else
{
// combo list not dropped
int nSize = m_list.size();
m_iter = m_list.begin();
if (m_nCurSel < 0 || m_nCurSel >= nSize)
m_nCurSel = 0;
advance(m_iter, m_nCurSel);
int nOldSel = m_nCurSel;
int nPos = m_nCurSel;
// Page Up goes back by 10
for (int i = 0; i < 10; i++)
{
if (nPos <= 0)
{
nPos = 0;
break;
}
nPos--;
m_iter--;
}
if (nOldSel != nPos)
{
m_strEdit = m_iter->strText;
if (m_pEdit)
m_pEdit->SetWindowText(m_strEdit.c_str());
Invalidate();
m_nCurSel = nPos;
// Send message to parent(dialog)
int nId = GetDlgCtrlID();
m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDOK), (LPARAM)m_hWnd );
m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELCHANGE), (LPARAM)m_hWnd );
}
}
}
int CAdvComboBox::GetTopIndex()
{
if( m_bDropListVisible )
{
if( m_pDropWnd )
{
return m_pDropWnd->GetListBoxPtr()->GetTopIndex();
}
}
return CB_ERR;
}
int CAdvComboBox::SetTopIndex(int nIndex)
{
if( m_bDropListVisible )
{
if( m_pDropWnd )
{
return m_pDropWnd->GetListBoxPtr()->SetTopIndex(nIndex);
}
}
return CB_ERR;
}
//
// Will not allocate anything. I can't see the need in doing that.
// Everything is stored in a STL list.
int CAdvComboBox::InitStorage(int nItems, UINT /*nBytes*/)
{
return nItems;
}
void CAdvComboBox::ShowDropDown(BOOL bShowIt)
{
if( bShowIt )
{
if( !m_bDropListVisible )
{
SendMessage( WM_ON_DROPDOWN_BUTTON );
Invalidate();
}
}
else
{
if( m_bDropListVisible )
{
SendMessage( WM_DESTROY_DROPLIST );
Invalidate();
}
}
}
void CAdvComboBox::GetDroppedControlRect(LPRECT lprect)
{
if( m_bDropListVisible )
{
m_pDropWnd->GetWindowRect( lprect );
}
}
BOOL CAdvComboBox::GetDroppedState()
{
return m_bDropListVisible;
}
int CAdvComboBox::SetExtendedUI(BOOL /*bExtended*/)
{
return CB_OKAY;
}
BOOL CAdvComboBox::GetExtendedUI()
{
return FALSE;
}
int CAdvComboBox::DeleteString(UINT nIndex)
{
m_iter = m_list.begin();
advance( m_iter, nIndex );
if( m_iter != m_list.end() || nIndex > m_list.size() )
{
m_list.erase( m_iter );
return m_list.size();
}
else
{
return CB_ERR;
}
}
int CAdvComboBox::InsertString(int nIndex, LPCTSTR lpszString)
{
LIST_ITEM item;
item.strText = lpszString;
if( nIndex == -1 || (nIndex > (int)m_list.size()) )
{
m_list.push_back( item );
return m_list.size()-1;
}
if( nIndex == 0 && (m_list.size()==0) )
{
m_list.push_back( item );
return 0;
}
m_iter = m_list.begin();
advance( m_iter, nIndex );
if( m_iter != m_list.end() )
{
m_iter = m_list.insert( m_iter, item );
int nPos = 0;
while( m_iter != m_list.begin() )
{
nPos++;
--m_iter;
}
if( nIndex <= m_nCurSel )
{
m_nCurSel++;
}
return nPos;
}
return CB_ERR;
}
DWORD CAdvComboBox::GetEditSel()
{
if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
{
if( m_pEdit )
{
return m_pEdit->GetSel();
}
}
return (DWORD)CB_ERR;
}
BOOL CAdvComboBox::SetEditSel(int nStartChar, int nEndChar)
{
if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
{
if( m_pEdit )
{
m_pEdit->SetSel( nStartChar, nEndChar, TRUE );
return TRUE;
}
}
return CB_ERR;
}
void CAdvComboBox::OnChangeEdit()
{
if( !m_pDropWnd )
{
// Send message to parent(dialog)
int nId = GetDlgCtrlID();
m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_EDITCHANGE), (LPARAM)m_hWnd );
}
}
void CAdvComboBox::OnUpdateEdit()
{
static bool bAutoAppendInProgress;
CString strEdit;
m_pEdit->GetWindowText( strEdit );
if( GetFocus() == m_pEdit )
{
if( !bAutoAppendInProgress )
{
// m_nCurSel = -1;
if( m_dwACBStyle & ACBS_AUTOAPPEND && m_bAutoAppend )
{
tstring str = (LPCTSTR)strEdit;
int nEditLen = str.length();
if( !nEditLen )
return;
int nStartSel;
int nEndSel;
m_pEdit->GetSel( nStartSel, nEndSel );
LIST_ITEM item;
m_iter = m_list.begin();
while( m_iter != m_list.end() )
{
item = *m_iter;
int nPos = m_iter->strText.find( str, 0 );
if( nPos == 0 )
{
bAutoAppendInProgress = true;
m_pEdit->SetWindowText( m_iter->strText.c_str() );
m_pEdit->SetSel( nEditLen, m_iter->strText.length(), TRUE );
bAutoAppendInProgress = false;
break;
}
++m_iter;
}
}
}
if( !bAutoAppendInProgress )
{
if( m_dwACBStyle & ACBS_AUTOSUGGEST )
{
list<LIST_ITEM> suggestlist;
list<LIST_ITEM>::iterator suggestiter;
tstring str = (LPCTSTR)strEdit;
int nEditLen = str.length();
if( !nEditLen )
{
if( m_pDropWnd )
SendMessage( WM_DESTROY_DROPLIST );
return;
}
int nStartSel;
int nEndSel;
m_pEdit->GetSel( nStartSel, nEndSel );
LIST_ITEM item;
m_iter = m_list.begin();
while( m_iter != m_list.end() )
{
item = *m_iter;
int nPos = m_iter->strText.find( str, 0 );
if( nPos == 0 )
{
if (m_iter->strText != str) //+++
suggestlist.push_back( item );
}
++m_iter;
}
if( m_pDropWnd )
SendMessage( WM_DESTROY_DROPLIST );
//+++if( suggestlist.size() != 0 )
if( suggestlist.size() > 1 ) //+++
{
m_nCurSel = 0; //+++
CreateDropList( suggestlist );
}
}
}
}
if( !m_pDropWnd )
{
// Send message to parent(dialog)
int nId = GetDlgCtrlID();
m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_EDITUPDATE), (LPARAM)m_hWnd );
}
}
void CAdvComboBox::OnEnable(BOOL bEnable)
{
CWnd::OnEnable(bEnable);
Invalidate();
if( m_pEdit )
{
m_pEdit->EnableWindow( bEnable );
}
}
BOOL CAdvComboBox::LimitText(int nMaxChars)
{
if( m_pEdit )
{
int nCh = !nMaxChars ? 65535 : nMaxChars;
m_pEdit->SetLimitText( nCh );
return TRUE;
}
else
{
return CB_ERR;
}
}
void CAdvComboBox::SetMinVisibleItems(int nMinItems)
{
m_nMinVisItems = nMinItems;
}
int CAdvComboBox::GetMinVisibleItems()
{
return m_nMinVisItems;
}
void CAdvComboBox::OnMouseMove(UINT nFlags, CPoint point)
{
bool bChange = m_bDropButtonHot;
if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
{
if( m_rcDropButton.PtInRect( point ) )
{
m_bDropButtonHot = true;
}
else
{
m_bDropButtonHot = false;
}
}
else
if( (GetStyle() & CBS_DROPDOWN) && (GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWNLIST
{
GetClientRect( &m_rcCombo );
if( m_rcCombo.PtInRect( point ) )
{
m_bDropButtonHot = true;
}
else
{
m_bDropButtonHot = false;
}
}
if( bChange != m_bDropButtonHot )
{
if( !m_bTrackMouseLeave )
{
//
// Could not use TrackMouseEvent() under Release. A bug appeared
// the second time the dropwindow was shown, and I did not
// have to strenght to go look for it. :)
/* TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hWnd;
TrackMouseEvent(&tme);*/
m_bTrackMouseLeave = true;
SetTimer(1, 50, NULL);
}
InvalidateRect( &m_rcDropButton );
}
CWnd::OnMouseMove(nFlags, point);
}
void CAdvComboBox::OnMouseLeave()
{
// TODO: Add your message handler code here and/or call default
bool bChange = m_bDropButtonHot;
m_bDropButtonHot = false;
m_bTrackMouseLeave = false;
if( bChange != m_bDropButtonHot )
InvalidateRect( &m_rcDropButton );
}
void CAdvComboBox::OnTimer(UINT nIDEvent)
{
if( nIDEvent == 1 )
{
CPoint point;
GetCursorPos( &point );
ScreenToClient( &point );
if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
{
if( !m_rcDropButton.PtInRect( point ) )
{
KillTimer( 1 );
OnMouseLeave();
}
}
else
if( (GetStyle() & CBS_DROPDOWN) && (GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWNLIST
{
GetClientRect( &m_rcCombo );
if( !m_rcCombo.PtInRect( point ) )
{
KillTimer( 1 );
OnMouseLeave();
}
}
}
CWnd::OnTimer(nIDEvent);
}
int CAdvComboBox::GetDefaultVisibleItems()
{
return m_nDefaultDropItems;
}
void CAdvComboBox::SetDefaultVisibleItems(int nItems)
{
m_nDefaultDropItems = nItems;
}
//+++
// function to get combo width based on strings
UINT CAdvComboBox::GetComboWidth()
{
CDC * pDC = GetDC();
CFont * pFont = GetFont();
CFont* pOldFont = pDC->SelectObject(pFont);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
CString str = _T("");
CSize sz;
UINT dx = 0;
for (int i = 0; i < GetCount(); i++)
{
GetLBText(i, str);
sz = pDC->GetTextExtent(str);
sz.cx += tm.tmAveCharWidth;
if (sz.cx > (int)dx)
dx = sz.cx;
}
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);
dx += ::GetSystemMetrics(SM_CXVSCROLL) + 2*::GetSystemMetrics(SM_CXEDGE) + 5;
return dx;
}
//+++
void CAdvComboBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// handle escape and return, in case combo's edit does NOT have focus
if (m_pParent)
{
if (nChar == VK_ESCAPE)
{
OnEscapeKey();
return;
}
else if (nChar == VK_RETURN)
{
OnComboComplete();
return;
}
else if (nChar == VK_DOWN)
{
SelNextItem();
}
}
CWnd::OnChar(nChar, nRepCnt, nFlags);
}
void CAdvComboBox::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// XLISTCTRL_TRACE(_T("in CAdvComboBox::OnKeyDown\n"));
if (nChar == VK_DOWN)
SelNextItem();
else if (nChar == VK_UP)
SelPrevItem();
else if (nChar == VK_NEXT)
SelNextPage();
else if (nChar == VK_PRIOR)
SelPrevPage();
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CAdvComboBox::OnActivateApp(BOOL bActive, HTASK hTask)
{
//XLISTCTRL_TRACE(_T("in CAdvComboBox::OnActivateApp\n"));
CWnd::OnActivateApp(bActive, hTask);
//CWnd::OnActivateApp(bActive, (DWORD)hTask);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -