MFC Combobox实现输入自动匹配
原文地址:https://blog.csdn.net/dyzhen/article/details/6185863
在原文的基础上, 修改了:
在函数 PreTranslateMessage 中, 处理 VK_RETURN 时.
1// 回车即选中高亮项
2SelectString(-1, strLine);
改为:
1int iSelectedRow = FindString(-1, strLine);
2if (-1 != iSelectedRow)
3{
4 SelectString(-1, strLine);
5}
这样就避免了未有匹配项时回车也会选择最后一个匹配到的项了.
1. 实现代码
头文件 ComboxAutoFill.h
1#pragma once
2
3
4// CComboxAutoFill
5
6#define WM_SHOWDROP WM_USER + 101
7
8class CComboxAutoFill : public CComboBox
9{
10 DECLARE_DYNAMIC(CComboxAutoFill)
11
12public:
13 CComboxAutoFill();
14 virtual ~CComboxAutoFill();
15
16protected:
17 DECLARE_MESSAGE_MAP()
18
19public:
20 afx_msg void OnCbnDropdown();
21 afx_msg void OnCbnEditupdate();
22 afx_msg HRESULT OnShowDropDown(WPARAM wParam, LPARAM lParam);
23 virtual BOOL PreTranslateMessage(MSG* pMsg);
24
25private:
26 BOOL m_bAutoComplete;
27};
源文件 ComboxAutoFill.cpp
1// ComboxAutoFill.cpp : implementation file
2//
3
4#include "stdafx.h"
5#include "ComboxAutoFill.h"
6
7#ifdef _DEBUG
8#define new DEBUG_NEW
9#undef THIS_FILE
10static char THIS_FILE[] = __FILE__;
11#endif
12
13
14// CComboxAutoFill
15
16IMPLEMENT_DYNAMIC(CComboxAutoFill, CComboBox)
17
18CComboxAutoFill::CComboxAutoFill()
19{
20
21}
22
23CComboxAutoFill::~CComboxAutoFill()
24{
25}
26
27
28BEGIN_MESSAGE_MAP(CComboxAutoFill, CComboBox)
29 ON_CONTROL_REFLECT(CBN_DROPDOWN, &CComboxAutoFill::OnCbnDropdown)
30 ON_CONTROL_REFLECT(CBN_EDITUPDATE, &CComboxAutoFill::OnCbnEditupdate)
31 ON_MESSAGE(WM_SHOWDROP, OnShowDropDown)
32END_MESSAGE_MAP()
33
34
35
36// CComboxAutoFill message handlers
37
38
39BOOL CComboxAutoFill::PreTranslateMessage(MSG* pMsg)
40{
41 if (pMsg->message == WM_CHAR)
42 {
43 m_bAutoComplete = TRUE;
44
45 int nVirKey = pMsg->wParam;
46
47 switch (nVirKey)
48 {
49 case VK_RETURN:
50 {
51 // 关闭下拉框
52 ShowDropDown(FALSE);
53
54 CString strLine;
55 GetWindowText(strLine);
56
57 // 回车即选中高亮项(只有匹配时才设置为已选)
58 int iSelectedRow = FindString(-1, strLine);
59 if (-1 != iSelectedRow)
60 {
61 SelectString(-1, strLine);
62 }
63
64 // 给父窗口发送选项改变的消息
65 WPARAM wParam = MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE);
66 GetParent()->PostMessage(WM_COMMAND, wParam, (LPARAM)m_hWnd);
67
68 break;
69 }
70
71 case VK_DELETE:
72 case VK_BACK:
73
74 m_bAutoComplete = FALSE;
75
76 break;
77
78 default:
79 break;
80 }
81
82 }
83
84 return CComboBox::PreTranslateMessage(pMsg);
85}
86
87void CComboxAutoFill::OnCbnDropdown()
88{
89 SetCursor(LoadCursor(NULL, IDC_ARROW));
90}
91
92
93void CComboxAutoFill::OnCbnEditupdate()
94{
95 CString strLine;
96 GetWindowText(strLine);
97
98 int iHiLightStart = strLine.GetLength();
99
100 if (strLine.GetLength() == 0)
101 {
102 ShowDropDown(FALSE);
103 SetWindowText(_T(""));
104 m_bAutoComplete = TRUE;
105 return;
106 }
107
108 // 处理删除操作
109 if (!m_bAutoComplete)
110 {
111 m_bAutoComplete = TRUE;
112 return;
113 }
114
115 // 开始匹配用户输入
116 int iSelectedRow = FindString(-1, strLine);
117 if (iSelectedRow >= 0)
118 {
119 // ShowDropDown(TRUE);
120 PostMessage(WM_SHOWDROP, 0, 0);
121
122 // 匹配的选项被选中
123 PostMessage(CB_SETCURSEL, iSelectedRow, 0);
124
125 // 给父窗口发送选项改变的消息,这样可以保证当输入完整的匹配的部门时,不用回车也触发部门改变消息
126 WPARAM wParam = MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE);
127 GetParent()->PostMessage(WM_COMMAND, wParam, (LPARAM)m_hWnd);
128 }
129 else
130 {
131 // ShowDropDown(FALSE);
132 // SetWindowText(strLine);
133 }
134
135 // 高亮自动完成的部分
136 PostMessage(CB_SETEDITSEL, 0, MAKELPARAM(iHiLightStart, -1));
137}
138
139HRESULT CComboxAutoFill::OnShowDropDown(WPARAM wParam, LPARAM lParam)
140{
141 ShowDropDown(TRUE);
142
143 return 0;
144}
2. 调用
1CComboxAutoFill m_ComboxAutoFill;
2
3CRect rc;
4rc.left = 20;
5rc.top = 20;
6rc.right = 100;
7rc.bottom = rc.top + 30;
8
9// 格式为DROPDOWN, 支持下拉框带滚动条, 支持tab
10m_ComboxAutoFill.Create(CBS_DROPDOWN | WS_VISIBLE | WS_VSCROLL | WS_CHILD | WS_TABSTOP, rc, this, 22333);
11
12// 设置字体
13m_ComboxAutoFill.SetFont(this->GetFont());
14
15// 测试数据
16for (int i = 100; i < 200; i++)
17{
18 CString str;
19 str.Format(_T("A%03d"), i);
20 m_ComboxAutoFill.InsertString(0, str);
21}
22for (int i = 1000; i < 1124; i++)
23{
24 CString str;
25 str.Format(_T("B%04d"), i);
26 m_ComboxAutoFill.InsertString(0, str);
27}
28
29m_ComboxAutoFill.BringWindowToTop();