VC++ combobox模糊匹配,自动匹配

来源:互联网 发布:家庭矛盾 知乎 编辑:程序博客网 时间:2024/05/22 06:10

借鉴文章

http://blog.csdn.net/lsldd/article/details/4595386

http://blog.csdn.net/dyzhen/article/details/6185863

谢谢以上两位大神

(1) 使在输入了一个完整的匹配项,或者回车选中某项时,触发CBN_SELCHANGE消息.

(2) ShowDropDown(TRUE)采用消息迂回调用.原因如下,当输入中文词组时,OnEditUpdate会逐字依次调用,也就是说一次性输入几个汉字它就调用几次,而在此当中直接调用ShowDropDown(TRUE)会导致组合框Edit框的内容瞬间变成了匹配选项的内容,且为高亮选中状态,OnEditUpdate接下去处理接下来的汉字的时候,就仅把这一个汉字当成了输入内容,前面的内容就丢失了,所以导致匹配失效. (哎...说的自己都不明白...调试跟踪就知道是咋回事了).

 

本文首先派生了一个CComboBox类CComboCompletion,然后增加虚函数PreTranslateMessage,处理键盘输入,然后增加CBN_DROPDOWN和CBN_EDITUPDATE消息的处理.


头文件ComboCompletion.h:

#if !defined(AFX_COMBOCOMPLETION_H__9255E6D2_71F7_48CD_B6F5_5B249E0BE307__INCLUDED_)#define AFX_COMBOCOMPLETION_H__9255E6D2_71F7_48CD_B6F5_5B249E0BE307__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000// ComboCompletion.h : header file///////////////////////////////////////////////////////////////////////////////// CComboCompletion window#define WM_SHOWDROP WM_USER + 101class CComboCompletion : public CComboBox{// Constructionpublic:CComboCompletion();// Attributespublic:// Operationspublic:// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CComboCompletion)public:virtual BOOL PreTranslateMessage(MSG* pMsg);//}}AFX_VIRTUAL// Implementationpublic:virtual ~CComboCompletion();// Generated message map functionsprotected://{{AFX_MSG(CComboCompletion)afx_msg void OnDropdown();afx_msg void OnEditupdate();afx_msg HRESULT OnShowDropDown(WPARAM wParam, LPARAM lParam);//}}AFX_MSGDECLARE_MESSAGE_MAP()private:BOOL m_bAutoComplete;};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_COMBOCOMPLETION_H__9255E6D2_71F7_48CD_B6F5_5B249E0BE307__INCLUDED_)

ComboCompletion.cpp

// ComboCompletion.cpp : implementation file//#include "stdafx.h"#include "hrinetnsm_con.h"#include "ComboCompletion.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CComboCompletionCComboCompletion::CComboCompletion(){}CComboCompletion::~CComboCompletion(){}BEGIN_MESSAGE_MAP(CComboCompletion, CComboBox)//{{AFX_MSG_MAP(CComboCompletion)ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown)ON_CONTROL_REFLECT(CBN_EDITUPDATE, OnEditupdate)//}}AFX_MSG_MAPON_MESSAGE(WM_SHOWDROP, OnShowDropDown)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CComboCompletion message handlersBOOL CComboCompletion::PreTranslateMessage(MSG* pMsg) {// TODO: Add your specialized code here and/or call the base classif (pMsg->message == WM_CHAR){m_bAutoComplete = TRUE;int nVirKey = pMsg->wParam;switch (nVirKey){case VK_RETURN:{// 关闭下拉框ShowDropDown(FALSE);CString strLine;GetWindowText(strLine);// 回车即选中高亮项SelectString(-1, strLine);// 给父窗口发送选项改变的消息WPARAM wParam = MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE);GetParent()->PostMessage(WM_COMMAND, wParam, (LPARAM)m_hWnd);break;}case VK_DELETE:case VK_BACK:m_bAutoComplete = FALSE;break;default:break;}}return CComboBox::PreTranslateMessage(pMsg);}void CComboCompletion::OnDropdown() {// TODO: Add your control notification handler code hereSetCursor(LoadCursor(NULL, IDC_ARROW));  }void CComboCompletion::OnEditupdate() {// TODO: Add your control notification handler code hereCString strLine;    GetWindowText(strLine);  int iHiLightStart = strLine.GetLength();  if(strLine.GetLength() == 0)   {  ShowDropDown(FALSE);  SetWindowText(_T(""));   m_bAutoComplete = TRUE;  return;  }  // 处理删除操作 if(!m_bAutoComplete)  {          m_bAutoComplete = TRUE;  return;  }  // 开始匹配用户输入  int iSelectedRow = FindString(-1, strLine);  if(iSelectedRow >= 0)  {//    ShowDropDown(TRUE);  PostMessage(WM_SHOWDROP, 0, 0);// 匹配的选项被选中  PostMessage(CB_SETCURSEL, iSelectedRow, 0);  // 给父窗口发送选项改变的消息,这样可以保证当输入完整的匹配的部门时,不用回车也触发部门改变消息WPARAM wParam = MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE);GetParent()->PostMessage(WM_COMMAND, wParam, (LPARAM)m_hWnd);}  else   {  //         ShowDropDown(FALSE);  //         SetWindowText(strLine);  }  // 高亮自动完成的部分PostMessage(CB_SETEDITSEL, 0, MAKELPARAM(iHiLightStart, -1));  }HRESULT CComboCompletion::OnShowDropDown(WPARAM wParam, LPARAM lParam){ShowDropDown(TRUE);return 0;}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

后来发现这个类还是不能满足条件,领导希望输入首字母,自动补全的同时还要删除无关信息,终于在pudn找到一个

AutoCombox1.h

#pragma once// CAutoCombox1class CAutoCombox1 : public CComboBox{DECLARE_DYNAMIC(CAutoCombox1)public:CAutoCombox1();virtual ~CAutoCombox1();// manipulating listbox itemsint AddString(LPCTSTR lpszString);int DeleteString(UINT nIndex);int InsertString(int nIndex, LPCTSTR lpszString);void ResetContent();//set statevoid SetFlag(UINT nFlag){m_nFlag = nFlag;}private:int Dir(UINT attr, LPCTSTR lpszWildCard){ASSERT(FALSE);}//forbiddenprotected:virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);void AutoSelect();void AutoMatchAndSel();DECLARE_MESSAGE_MAP()private:CEdit* m_pEdit;//edit controlUINT m_nFlag;//some flag//bit 0: 0 is show all, 1 is remove not matching, if no maching, show all.CStringArray m_strArr;};

AutoCombox1.cpp

// AutoCombox1.cpp : implementation file//#include "stdafx.h"// #include "MyCombox.h"#include "AutoCombox1.h"// CAutoCombox1IMPLEMENT_DYNAMIC(CAutoCombox1, CComboBox)CAutoCombox1::CAutoCombox1(){m_pEdit = NULL;m_nFlag = 0;}CAutoCombox1::~CAutoCombox1(){if (m_pEdit){if (::IsWindow(m_hWnd)){m_pEdit->UnsubclassWindow();}delete m_pEdit;m_pEdit = NULL;}}BEGIN_MESSAGE_MAP(CAutoCombox1, CComboBox)END_MESSAGE_MAP()// CAutoCombox1 message handlers//自动选择最匹配的,如果没有,则不选择。////////////////////////////////void CAutoCombox1::AutoSelect(){// Make sure we can 'talk' to the edit controlif ( m_pEdit == NULL )  {m_pEdit = new CEdit();m_pEdit->SubclassWindow(GetDlgItem(1001)->GetSafeHwnd());}// Save the state of the edit controlCString strText;//取得输入字符串int nStart = 0, nEnd = 0;//取得光标位置m_pEdit->GetWindowText(strText);m_pEdit->GetSel(nStart, nEnd);// Perform actual completionint nBestIndex = -1;//是否能找到匹配的字符int nBestFrom  = INT_MAX;//匹配开始的字符if (!strText.IsEmpty()){for ( int nIndex=0; nIndex<GetCount(); ++nIndex ){CString str;GetLBText(nIndex,str);int nFrom = str.Find(strText);if ( nFrom != -1 && nFrom < nBestFrom )//能匹配,而且是更好的匹配,才记录{nBestIndex = nIndex;nBestFrom  = nFrom;}}//for}//Set select indexif (!GetDroppedState()){ShowDropDown(TRUE);m_pEdit->SetWindowText(strText);m_pEdit->SetSel(nStart, nEnd);}if ( GetCurSel() != nBestIndex ){// Select the matching entry in the listSetCurSel(nBestIndex);// Restore the edit controlm_pEdit->SetWindowText(strText);m_pEdit->SetSel(nStart, nEnd);}}//删除不匹配的,自动选择剩余中最匹配的,如果没有,则显示全部。//////////////void CAutoCombox1::AutoMatchAndSel(){// Make sure we can 'talk' to the edit controlif ( m_pEdit == NULL )  {m_pEdit = new CEdit();m_pEdit->SubclassWindow(GetDlgItem(1001)->GetSafeHwnd());}// 保存edit控件的状态CString strText;//取得输入字符串int nStart = 0, nEnd = 0;//取得光标位置m_pEdit->GetWindowText(strText);m_pEdit->GetSel(nStart, nEnd);//清空CComboBox里面的数据CComboBox::ResetContent();// 重新填充列表,并选择最合适的int nBestIndex = -1;//是否能找到匹配的字符int nBestFrom  = INT_MAX;//匹配开始的字符if (!strText.IsEmpty()){for ( int nIndex=0; nIndex<m_strArr.GetSize(); ++nIndex ){int nFrom = m_strArr[nIndex].Find(strText);char kk = m_strArr[nIndex].GetAt(0);char jj = strText.GetAt(0);BOOL flag = FALSE;if (kk==jj){flag = TRUE;}if ( nFrom != -1&&flag==TRUE)//能匹配{int n = CComboBox::AddString(m_strArr[nIndex]);if (nFrom < nBestFrom)//更好的匹配,则记录{nBestIndex = n;nBestFrom  = nFrom;}}}//for}if (GetCount() == 0)//没有的显示所有{for (int nIndex=0; nIndex<m_strArr.GetSize(); ++nIndex){CComboBox::AddString(m_strArr[nIndex]);}}//显示下拉列表if (!GetDroppedState()){ShowDropDown(TRUE);}//设置选择项// Select and Restore the edit controlSetCurSel(nBestIndex);m_pEdit->SetWindowText(strText);m_pEdit->SetSel(nStart, nEnd);}// manipulating listbox itemsint  CAutoCombox1::AddString(LPCTSTR lpszString){m_strArr.Add(lpszString);return CComboBox::AddString(lpszString);}int  CAutoCombox1::DeleteString(UINT nIndex){m_strArr.RemoveAt(nIndex);return CComboBox::DeleteString(nIndex);}int  CAutoCombox1::InsertString(int nIndex, LPCTSTR lpszString){m_strArr.InsertAt(nIndex, lpszString);return CComboBox::InsertString(nIndex, lpszString);}void  CAutoCombox1::ResetContent(){m_strArr.RemoveAll();CComboBox::ResetContent();}//All Message Handle DispatchBOOL CAutoCombox1::OnCommand(WPARAM wParam, LPARAM lParam){if ( HIWORD(wParam) == EN_CHANGE ){if (m_nFlag & 0x01){AutoMatchAndSel();}else{AutoSelect();}return true;}else{return CComboBox::OnCommand(wParam, lParam);}}

=================================================================================================================

程序猿和程序媛必备的咖啡-OneDay咖啡生活-https://shop110384469.taobao.com/


0 0
原创粉丝点击