ComboBox自动下拉列表框并使列表项为选中状态

wfonly 2010-08-27 02:12:30
请问大侠们,一下是一段代码,可以实现自动匹配并显示在ComboBox的编辑框里,我想要在编辑框里输入的时候,列表框自动下拉,并使匹配的项为选中状态,不知该如何实现,请前辈们不吝赐予一些代码,在下谢过了先!
BOOL CAutoCompleteComboBox::PreTranslateMessage(MSG* pMsg) 
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_KEYDOWN)
{
m_bWorkOnText = TRUE;

int nVKey = (int) pMsg->wParam;
if (nVKey == VK_DELETE || nVKey == VK_BACK)
m_bWorkOnText = FALSE;
}

return CComboBox::PreTranslateMessage(pMsg);
}

void CAutoCompleteComboBox::OnEditUpdate()
{
// TODO: Add your control notification handler code here
if (!m_bWorkOnText)
return;

//取得编辑框中的文字;
CString strWindowText;
GetWindowText(strWindowText);
int nLength = strWindowText.GetLength();

//取得当前的选择范围
DWORD dwCurSel = GetEditSel();
WORD dStart = LOWORD(dwCurSel);
WORD dEnd = HIWORD(dwCurSel);

// 实际做查找和选择的语句
if (SelectString(-1, strWindowText) == CB_ERR)
{
SetWindowText(strWindowText); // 恢复文字
if (dwCurSel != CB_ERR)
SetEditSel(dStart, dEnd); // 恢复原先的位置
}

// 把添加的文字做为选择的文字
if (dEnd < nLength && dwCurSel != CB_ERR)
SetEditSel(dStart, dEnd);
else
SetEditSel(nLength, -1);
}
...全文
1323 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
jacky_qiu 2010-08-30
  • 打赏
  • 举报
回复
楼上高手已经帮你解决了。愿一切顺利!。
wfonly 2010-08-30
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 gameslq 的回复:]
引用 22 楼 wfonly 的回复:

去掉蓝条:
SetCurSel(-1);
[/Quote]

这样的话是不是就把编辑框里的已输入部分都清除了就
gameslq 2010-08-30
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 wfonly 的回复:]
功能基本可以实现了,谢谢各位前辈的帮助,还有个小问题,如果继续输入时在列表框找不到匹配项,那么如何使已产生的蓝色高亮条去掉呢?
[/Quote]

去掉蓝条:
SetCurSel(-1);
wfonly 2010-08-30
  • 打赏
  • 举报
回复
功能基本可以实现了,谢谢各位前辈的帮助,还有个小问题,如果继续输入时在列表框找不到匹配项,那么如何使已产生的蓝色高亮条去掉呢?
gameslq 2010-08-30
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 wfonly 的回复:]
#16楼 我根据你的程序和我之前那部分程序,修改成下面一个,但是就是不能再列表框里高亮显示,这是为什么啊
BOOL CAutoCompleteComboBox::OnCommand(WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class

i……
[/Quote]
1.在OnCommand处理完后,要返回值
改为以下逻辑:

if ( HIWORD(wParam) == EN_CHANGE )
{
.....
return TRUE;//不用系统再处理
}
else
return CComboBox::OnCommand(wParam, lParam);//不处理的让系统处理



2.最好把以下两个放到前面

ShowDropDown(TRUE); //使用这个鼠标会不见
::SetCursor(::LoadCursor(NULL,IDC_ARROW)); //重新显示鼠标

使输入字后下拉列表就出现.
3.SelectString(-1, strWindowText)) == CB_ERR
最好能改成模糊匹配.
wfonly 2010-08-30
  • 打赏
  • 举报
回复
#16楼 我根据你的程序和我之前那部分程序,修改成下面一个,但是就是不能再列表框里高亮显示,这是为什么啊
BOOL CAutoCompleteComboBox::OnCommand(WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class

if ( HIWORD(wParam) == EN_CHANGE )
{
if (!m_bWorkOnText)
return true;

//取得编辑框中的文字;
CString strWindowText;
GetWindowText(strWindowText);
int nLength = strWindowText.GetLength();

//取得当前的选择范围
DWORD dwCurSel = GetEditSel();
WORD dStart = LOWORD(dwCurSel);
WORD dEnd = HIWORD(dwCurSel);

// 实际做查找和选择的语句
int nChoice;
if ((nChoice=SelectString(-1, strWindowText)) == CB_ERR)
{
SetWindowText(strWindowText); // 恢复文字
if (dwCurSel != CB_ERR)
SetEditSel(dStart, dEnd); // 恢复原先的位置
}
else
{
ShowDropDown(TRUE); //使用这个鼠标会不见
::SetCursor(::LoadCursor(NULL,IDC_ARROW)); //重新显示鼠标
SetCurSel(nChoice);//此处想在列表里蓝色显示,但是不行,为什么???????

}

// 把添加的文字做为选择的文字
if (dEnd < nLength && dwCurSel != CB_ERR)
SetEditSel(dStart, dEnd);
else
SetEditSel(nLength, -1);
Waldenz 2010-08-30
  • 打赏
  • 举报
回复
c++不会啊
wfonly 2010-08-30
  • 打赏
  • 举报
回复
#16楼 jacky_qiu 兄,非常感谢你的代码,但还有一个问题,就是我想要编辑框里的输入项是按顺序查找的,不是如果列表框里有包含这个字符就匹配的,例如我输入a,列表框会匹配a****,而不是***a*,如果首字母没有的a的话,就不进行匹配,这样好改么?
wfonly 2010-08-30
  • 打赏
  • 举报
回复
再次非常谢谢jacky_qiu , gameslq 二位前辈的帮助,现在已经可以完美实现想要的功能了,同样祝愿二位一切顺利!
schlafenhamster 2010-08-29
  • 打赏
  • 举报
回复
//.h
class CxxxxDlg : public CDialog
{
// Dialog Data
//{{AFX_DATA(CxxxxDlg)
enum { IDD = IDD_xxxx_DIALOG };
CEdit m_EditCb;//classwizard 产生2个变量代替combo
CListBox m_ListCb;
//.cpp, init
m_ListCb.AddString("1");
m_ListCb.AddString("2");
m_ListCb.AddString("3");
m_ListCb.AddString("4");
m_ListCb.AddString("5");
m_ListCb.AddString("6");
m_ListCb.AddString("7");
m_ListCb.SetCurSel(0);
m_ListCb.ShowWindow(SW_HIDE);
//
void CxxxxDlg::OnChangeEdit1()
{//m_EditCb
// TODO: Add your control notification handler code here
m_ListCb.ShowWindow(SW_SHOW);
// 匹配list中内容后得到匹配项的 idx
m_ListCb.SetCurSel(2);
}

void CxxxxDlg::OnSelchangeList1()
{//m_ListCb
// TODO: Add your control notification handler code here
int idx;
CString str;
idx=m_ListCb.GetCurSel();
m_ListCb.GetText(idx,str);
m_EditCb.SetWindowText(str);
m_ListCb.ShowWindow(SW_HIDE);
}


dvlinker 2010-08-29
  • 打赏
  • 举报
回复
顶一个~
jacky_qiu 2010-08-29
  • 打赏
  • 举报
回复
刚刚再修改一下,这个应该满足你的要求了。阿弥陀佛! ^-^
1.每次edit box 变化时,都调用ShowDropDown显示下拉列表
//show drop menu
ShowDropDown(TRUE); //使用这个鼠标会不见
::SetCursor(::LoadCursor(NULL,IDC_ARROW)); //重新显示鼠标

2.记住千万不要在添加消息里的 CBN_EDITCHANGE ,即 void AutoCompletion::OnEditchange()
函数里处理自动完成的事情,否则SetCurSel(bestindex) 无法选择item,我开始也怀疑作者
为什么非要在OnCommand函数里写代码,后来调试很久才知道必须如此。


3.示例程序下载:http://cid-3ba16e78a53d2d3d.office.live.com/self.aspx/VC%5EM%5EM/4%20ComboBox%5E_%E9%80%89%E4%B8%AD%E5%88%97%E8%A1%A8%E9%A1%B9.zip

4.新建一个类继承于CComboBox,添加OnCommand消息。在里面添加以下代码即可

BOOL AutoCompletion::OnCommand(WPARAM wParam, LPARAM lParam)
{
if ( HIWORD(wParam) == EN_CHANGE )
{
//show drop menu
ShowDropDown(TRUE); //使用这个鼠标会不见
::SetCursor(::LoadCursor(NULL,IDC_ARROW)); //重新显示鼠标

// Save the state of the edit control
CString windowtext;
GetWindowText(windowtext);

//if no text,return
if ( windowtext.GetLength()==0)
{
SetCurSel(-1);
return true;
}

// Currently selected range
DWORD dwCurSel = GetEditSel();
WORD start = LOWORD(dwCurSel);
WORD end = HIWORD(dwCurSel);

// Perform actual completion
CString ItemText;
CString TempWindowText; //use for MakeUpper();
int FindItem;

int bestindex = -1;
int bestfrom = INT_MAX;
for ( int x = 0; x < GetCount(); x++ )
{
GetLBText(x,ItemText);

FindItem = ItemText.Find(windowtext);

//搜索结果不区分大小写,若搜索结构需要区分大小写,请去掉这一段
if(FindItem==-1)
{
ItemText.MakeUpper();
TempWindowText=windowtext;
TempWindowText.MakeUpper();
FindItem = ItemText.Find(TempWindowText);
}

if ( FindItem != -1 && FindItem < bestfrom )
{
bestindex = x;
bestfrom = FindItem;
}
}

if ( bestindex==-1) //no match item,so select none
SetCurSel(-1);
else if (GetCurSel() != bestindex)
{
// Select the matching entry in the list
SetCurSel(bestindex);
}

// Restore the edit control
SetWindowText(windowtext);
SetEditSel(start,end);

return true;
}
return CComboBox::OnCommand(wParam, lParam);
}
schlafenhamster 2010-08-29
  • 打赏
  • 举报
回复
不如把Combo去掉,直接用edit+list(=Combo)
gameslq 2010-08-29
  • 打赏
  • 举报
回复
#12 楼提供代码基本能解决楼主的问题
我这里也有个例子,不过是用win32开发的
http://www.codeproject.com/KB/winsdk/Win32AutoCompleteComboBox.aspx
wfonly 2010-08-29
  • 打赏
  • 举报
回复
感谢楼上的二位前辈,我试试
schlafenhamster 2010-08-29
  • 打赏
  • 举报
回复
我把#12楼的下载看了看,不错,不过还是有问题,如“点击Combo”-》显示list》输入a》list选择“aaaaa”》“点击list的aaaaa”》list消失,再到edit中改变“aaaaa”为‘a’》list不再显示。。。
jacky_qiu 2010-08-29
  • 打赏
  • 举报
回复
这里有个例子以前网上下载的,可以实现你的要求,但使用了ShowDropDown();这个函数后,发现鼠标不见了(也许是个bug吧)。效果不要。所以我做了些修改,当激活ComboBox是,模拟鼠标激活下拉菜单。当然按楼上的兄弟们所说的用edit和list来模拟确实是好方法。哈哈,我也这样做了
这个是原来作者的写的,感谢他。
http://cid-3ba16e78a53d2d3d.office.live.com/self.aspx/VC%5EM%5EM/autoselection%5E_combo.zip
这是我做了修改的例子(鼠标一激活ComboBox就会下拉菜单)
http://cid-3ba16e78a53d2d3d.office.live.com/self.aspx/VC%5EM%5EM/4%20ComboBox%5E_%E9%80%89%E4%B8%AD%E5%88%97%E8%A1%A8%E9%A1%B9.zip
wfonly 2010-08-28
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 visualeleven 的回复:]
这个你可以自己用CComoboBox+CListBox来解决。。。当在CComboBox的编辑框中输入的时候,在对应的位置上ShowWindow(SW_SHOW);来显示CListBox
[/Quote]

可以麻烦写些代码吗,谢谢了
Eleven 2010-08-28
  • 打赏
  • 举报
回复
这个你可以自己用CComoboBox+CListBox来解决。。。当在CComboBox的编辑框中输入的时候,在对应的位置上ShowWindow(SW_SHOW);来显示CListBox
wfonly 2010-08-28
  • 打赏
  • 举报
回复
上面那些代码已经可以实现查询了,现在就是想下拉和高亮显示
加载更多回复(6)

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧