在VS2010下,通过MFC用EditBox + ListBox自制ComboBox(附加简单的模糊搜索功能)

来源:互联网 发布:php 生成邀请码 编辑:程序博客网 时间:2024/04/27 05:42

       我在用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);}


在EditBox中输入数据时,自动搜索ListBox选项,可以通过EditBox的OnEnChange方法响应,再获取数据进行搜索实现:

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


本人编程新手,比较愚昧,以上内容如有问题或者更好的提议,欢迎提出。小弟非常乐意接受各位的指点。

原创粉丝点击