模糊搜索 支持虚拟键盘输入 定制组合框 MFC

2023-03-30  本文已影响0人  风轻云淡宇
1. 背景

用 MFC 的组合框可以做出很好模糊搜索效果,但有个硬伤,当用虚拟键盘输入时,组合框会因失去焦点自动收缩,无法展现想要搜索的项,所以就用 CEdit 和 CListBox 定制了一个支持虚拟键盘输入的模糊搜索组合框。

2.具体实现
2.1 具体界面布局如下:
界面布局

从工具箱拖拽一个CEdit和CListbox,并在CListbox下放四个按钮,用于演示下拉框收起时效果。

2.2 给下拉框添加数据
    for (int i = 0; i < 100; i++)
    {
        CString strData;
        srand((unsigned)time(NULL));

        strData.Format(_T("%d 内容%d"), rand()*(i+1), i);
        m_listBox.AddString(strData);
    }

这里随意添加一些数据到下拉框中。

2.3 监测编辑框输入变化的函数实现如下:
void CCboxCustmerDlg::OnEnChangeInput()
{
    CString strInput;

    ShowCbList(TRUE);
    m_bFind = FALSE;
    m_editInput.GetWindowText(strInput);


    if (!strInput.IsEmpty())
    {
        if (m_listBox.SelectString(-1, strInput) == CB_ERR)
        {
            Query(strInput);
        }
        else
        {
            CString strResult;
            m_listBox.SetCurSel(m_listBox.GetCurSel());
            m_listBox.GetText(m_listBox.GetCurSel(), strResult);
            m_bFind = FALSE;
        }
    }
    else
    {
        m_listBox.SetCurSel(-1);
    }
}

void CCboxCustmerDlg::ShowCbList(BOOL bShow)
{
    if (bShow)
    {
        m_listBox.ShowWindow(SW_SHOW);
        GetDlgItem(IDB_TEST1)->ShowWindow(SW_HIDE);
        GetDlgItem(IDB_TEST2)->ShowWindow(SW_HIDE);
        GetDlgItem(IDB_TEST3)->ShowWindow(SW_HIDE);
        GetDlgItem(IDB_TEST4)->ShowWindow(SW_HIDE);
    }
    else
    {
        m_listBox.ShowWindow(SW_HIDE);
        GetDlgItem(IDB_TEST1)->ShowWindow(SW_SHOW);
        GetDlgItem(IDB_TEST2)->ShowWindow(SW_SHOW);
        GetDlgItem(IDB_TEST3)->ShowWindow(SW_SHOW);
        GetDlgItem(IDB_TEST4)->ShowWindow(SW_SHOW);
    }
}
BOOL CCboxCustmerDlg::Query(CString strFind)
{
    CString strTemp;
    int iListTotal = m_listBox.GetCount();

    strFind.MakeUpper();
    for (int iTemp = 0; iTemp < iListTotal; iTemp++)
    {
        m_listBox.GetText(iTemp, strTemp);
        strTemp.MakeUpper();
        if (strTemp.Find(strFind.GetBuffer()) != -1)
        {
            m_bFind = TRUE;
            m_listBox.SetCurSel(iTemp);
            return TRUE;
        }
    }

    return FALSE;
}
2.4 以下对鼠标和键盘消息处理很关键,也很考验对 Windows 消息的处理能力,代码如下:
BOOL CCboxCustmerDlg::PreTranslateMessage(MSG* pMsg)
{
    if (WM_LBUTTONDOWN == pMsg->message)
    {
        if (pMsg->hwnd != GetDlgItem(IDC_LIST)->m_hWnd && pMsg->hwnd != GetDlgItem(IDE_INPUT)->m_hWnd)
        {
            SetFocus();
            ShowCbList(FALSE);
        }
    }
    else if (WM_LBUTTONUP == pMsg->message)
    {
        if (GetFocus() == GetDlgItem(IDC_LIST))
        {
            SetEditText();
            SetFocus();
            ShowCbList(FALSE);
        }
        else if (GetFocus() == GetDlgItem(IDE_INPUT))
        {
            if (m_bFind)
            {
                m_bFind = FALSE;
                ShowCbList(FALSE);
            }
        }
    }

    if (VK_DOWN == pMsg->wParam)
    {
        if (GetFocus() == GetDlgItem(IDE_INPUT))
        {
            m_listBox.SetFocus();
            m_listBox.SetCurSel(m_listBox.GetCurSel() + 1);
        }

    }
    else if (VK_UP == pMsg->wParam)
    {
        if (GetFocus() == GetDlgItem(IDE_INPUT))
        {
            m_listBox.SetFocus();

            if (m_listBox.GetCurSel() > 0)
            {
                m_listBox.SetCurSel(m_listBox.GetCurSel() - 1);
            }
            else
            {
                m_listBox.SetCurSel(0);
            }
        }
    }

    if (VK_RETURN == pMsg->wParam)
    {
        if (GetFocus() == GetDlgItem(IDE_INPUT) || GetFocus() == GetDlgItem(IDC_LIST))
        {
            SetEditText();
            ShowCbList(FALSE);
            
        }
        return FALSE;
    }

    return CDialogEx::PreTranslateMessage(pMsg);
}
上一篇 下一篇

猜你喜欢

热点阅读