带有输入自动匹配功能的Combobox

    技术2025-09-13  80

    原文地址:

    http://blog.csdn.net/lsldd/archive/2009/09/25/4595386.aspx

     

    在原文的基础上,修改了两点:

    (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 + 101 class CComboCompletion : public CComboBox { // Construction public: CComboCompletion(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{​{AFX_VIRTUAL(CComboCompletion) public: virtual BOOL PreTranslateMessage(MSG* pMsg); //}}AFX_VIRTUAL // Implementation public: virtual ~CComboCompletion(); // Generated message map functions protected: //{​{AFX_MSG(CComboCompletion) afx_msg void OnDropdown(); afx_msg void OnEditupdate(); afx_msg HRESULT OnShowDropDown(WPARAM wParam, LPARAM lParam); //}}AFX_MSG DECLARE_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_FILE static char THIS_FILE[] = __FILE__; #endif / // CComboCompletion CComboCompletion::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_MAP ON_MESSAGE(WM_SHOWDROP, OnShowDropDown) END_MESSAGE_MAP() / // CComboCompletion message handlers BOOL CComboCompletion::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if (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 here SetCursor(LoadCursor(NULL, IDC_ARROW)); } void CComboCompletion::OnEditupdate() { // TODO: Add your control notification handler code here CString 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; }

     

    最新回复(0)