1. 背景
在MFC应用程序中,标准组合框(ComboBox)支持模糊搜索,但在使用虚拟键盘时存在缺陷:输入时可能会失去焦点并自动收起,导致搜索结果无法展示。为解决此问题,我们采用CEdit
和CListBox
控件自定义实现支持虚拟键盘输入的模糊搜索组合框。
2. 具体实现
2.1 界面布局
根据提供的截图,界面包括:
- 一个输入框(
CEdit
) - 一个列表框(
CListBox
)用于展示搜索结果 - 四个按钮(
Btn1
)位于列表框下方,演示下拉框收起效果
2.2 添加数据到下拉框
循环随机生成数据并添加到列表框中:
srand(static_cast<unsigned>(time(NULL)));
for (int i = 0; i < 100; i++)
{
CString strData;
strData.Format(_T("%d 内容%d"), rand() * (i + 1), i);
m_listBox.AddString(strData);
}
2.3 监测编辑框输入变化
编辑框内容变化时,显示下拉框列表,并进行搜索匹配:
void CCboxCustmerDlg::OnEnChangeInput()
{
ShowCbList(TRUE);
m_bFind = FALSE;
CString strInput;
m_editInput.GetWindowText(strInput);
if (!strInput.IsEmpty())
{
int index = m_listBox.SelectString(-1, strInput);
if (index == CB_ERR)
{
m_bFind = Query(strInput);
}
else
{
m_listBox.SetCurSel(index);
}
}
else
{
m_listBox.SetCurSel(-1);
}
}
2.4 鼠标和键盘消息处理
处理鼠标点击和键盘按键消息,控制下拉框显示和隐藏:
BOOL CCboxCustmerDlg::PreTranslateMessage(MSG* pMsg)
{
switch (pMsg->message)
{
case WM_LBUTTONDOWN:
if (pMsg->hwnd != m_listBox.m_hWnd && pMsg->hwnd != m_editInput.m_hWnd)
{
SetFocus();
ShowCbList(FALSE);
}
break;
case WM_LBUTTONUP:
if (GetFocus() == m_listBox.m_hWnd)
{
SetEditText();
ShowCbList(FALSE);
}
else if (GetFocus() == m_editInput.m_hWnd && m_bFind)
{
ShowCbList(FALSE);
}
break;
case WM_KEYDOWN:
switch (pMsg->wParam)
{
case VK_DOWN:
if (GetFocus() == m_editInput.m_hWnd)
{
m_listBox.SetFocus();
m_listBox.SetCurSel(m_listBox.GetCurSel() + 1);
}
break;
case VK_UP:
if (GetFocus() == m_editInput.m_hWnd)
{
int curSel = m_listBox.GetCurSel();
m_listBox.SetCurSel(curSel > 0 ? curSel - 1 : 0);
}
break;
case VK_RETURN:
if (GetFocus() == m_editInput.m_hWnd || GetFocus() == m_listBox.m_hWnd)
{
SetEditText();
ShowCbList(FALSE);
}
return FALSE;
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
2.5 ShowCbList函数实现
控制下拉框及其相邻控件的显示与隐藏:
void CCboxCustmerDlg::ShowCbList(BOOL bShow)
{
m_listBox.ShowWindow(bShow ? SW_SHOW : SW_HIDE);
// 根据bShow参数显示或隐藏其他控件
}
2.6 Query函数实现
在列表框中查询包含指定字符串的项,并选中:
BOOL CCboxCustmerDlg::Query(CString strFind)
{
strFind.MakeUpper();
for (int i = 0; i < m_listBox.GetCount(); i++)
{
CString strItem;
m_listBox.GetText(i, strItem);
if (strItem.MakeUpper().Find(strFind) != -1)
{
m_listBox.SetCurSel(i);
return TRUE;
}
}
return FALSE;
}
结束语
通过上述实现,我们成功创建了一个支持虚拟键盘输入的自定义模糊搜索组合框,解决了传统组合框在使用虚拟键盘时的缺陷,提高了用户体验。