我在用MFC學習開發一些小工具時,使用過很多次ComboBox控件。雖然ComboBox很好用,新增的Ex還可以插入圖片,
但是有時遇到某些細節上的操作,會發現ComboBox控制起來還是很不自在,而且很難修改。
例如:我想通過在ComboBox的文本框輸入字符串,即可在下拉菜單下搜索匹配的一項(模糊搜索),但不知道爲什麼
總是指向該項時總是把文本框原有的輸入覆蓋掉(可能是默認自動選擇寫入文本框),文本框和下拉菜單之間功能實施綁
定在一起,暫時不知道如何各自分開控制(我並不想在下拉菜單上下移動時就給文本框賦值,求高手指導此解決方法)。
於是自制一個EditBox + ListBox合成的模擬ComboBox,這樣的好處就是操作上可以分開控制,而且我還可以幾個EditBox
共同控制同一個ListBox(可以根據EditBox的焦點指向方法響應,然後獲取ListBox的位置,最後顯示)。
操作上主要在PreTranslateMessage中通過控制焦點和指定的消息響應實現,代碼如下:
BOOL CTestMyComboDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加專用代碼和/或調用基類
if (GetFocus() != GetDlgItem(IDC_EDIT1) && GetFocus() != GetDlgItem(IDC_LIST1))
{
m_List1.ShowWindow(SW_HIDE);
}
else
{
m_List1.ShowWindow(SW_SHOW);
}
if(WM_LBUTTONUP == pMsg->message)
{
if (GetFocus() == GetDlgItem(IDC_LIST1))
{
SetEditText(); //該方法是把ListBox當前選擇寫入文本框
}
}
if (VK_DOWN == pMsg->wParam)
{
if (GetFocus() == GetDlgItem(IDC_EDIT1))
{
m_List1.SetFocus();
m_List1.SetCurSel(m_List1.GetCurSel() + 1);
}
if ((GetFocus()->GetParent()) == GetDlgItem(IDC_COMBO1))
{
m_Combo1.SetCurSel(m_Combo1.GetCurSel() + 1);
}
}
if (VK_UP == pMsg->wParam)
{
if (GetFocus() == GetDlgItem(IDC_EDIT1))
{
m_List1.SetFocus();
if (m_List1.GetCurSel() > 0)
{
m_List1.SetCurSel(m_List1.GetCurSel() - 1);
}
else
{
m_List1.SetCurSel(0);
}
}
}
if (VK_RETURN == pMsg->wParam)
{
if (GetFocus() == GetDlgItem(IDC_EDIT1) || GetFocus() == GetDlgItem(IDC_LIST1))
{
SetEditText();
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
void CTestMyComboDlg::OnEnChangeEdit1()
{
// TODO: 在此添加控件通知處理程序代碼
CString strEdit;
m_Edit1.GetWindowText(strEdit);
if (!strEdit.IsEmpty())
{
if (m_List1.SelectString(0, strEdit) == CB_ERR) //先用SelectString進行首字母匹配,如果匹配失敗再進行模糊匹配
{
SetFuzzyQuery(strEdit); //模糊匹配方法
}
}
else
{
m_List1.SetCurSel(-1);
}
}
簡單的模糊匹配方法,就是獲取ListBox的每一項字符串,然後通過CString::Find方法與要匹配的字符串進行比較(如果希望不分大小寫方式匹配,
可以在比較前把兩字符串先MakeUpper一下)。
int CTestMyComboDlg::SetFuzzyQuery(CString csEdit)
{
CString csTemp;
int iListTotal = m_List1.GetCount();
csEdit.MakeUpper();
for (int iTemp = 0; iTemp < iListTotal; iTemp++)
{
m_List1.GetText(iTemp, csTemp);
csTemp.MakeUpper();
if (csTemp.Find(csEdit.GetBuffer()) != -1)
{
m_List1.SetCurSel(iTemp);
break;
}
}
return 0;
}
有興趣可以參考本人的原測試工程:
http://download.csdn.net/detail/dante_vanc/4436120
本人編程新手,比較愚昧,以上內容如有問題或者更好的提議,歡迎提出。小弟非常樂意接受各位的指點。