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

时间:2022-12-22 19:49:01
请问大侠们,一下是一段代码,可以实现自动匹配并显示在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);
}

26 个解决方案

#1


如果选中的话就是SetSel

#2


麻烦能不能写写代码呀,在下菜鸟一个

#3


upup

#4


void CSuperComboBox::OnEditchange() 
{
// TODO: Add your control notification handler code here
ShowDropDown();//这个没问题
// SetCurSel(1);//这个不是你要的,你想叫匹配项变蓝色,对吧
}

#5


是的,列表框下拉后匹配项变成蓝色

#6


像是VC6“help”-》“index”那样的东西吧,要费点劲的。

#7


上面那些代码已经可以实现查询了,现在就是想下拉和高亮显示

#8


这个你可以自己用CComoboBox+CListBox来解决。。。当在CComboBox的编辑框中输入的时候,在对应的位置上ShowWindow(SW_SHOW);来显示CListBox

#9


引用 8 楼 visualeleven 的回复:
这个你可以自己用CComoboBox+CListBox来解决。。。当在CComboBox的编辑框中输入的时候,在对应的位置上ShowWindow(SW_SHOW);来显示CListBox


可以麻烦写些代码吗,谢谢了

#10


不如把Combo去掉,直接用edit+list(=Combo)

#11


//.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);
}


#12


这里有个例子以前网上下载的,可以实现你的要求,但使用了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

#13


我把#12楼的下载看了看,不错,不过还是有问题,如“点击Combo”-》显示list》输入a》list选择“aaaaa”》“点击list的aaaaa”》list消失,再到edit中改变“aaaaa”为‘a’》list不再显示。。。

#14


感谢楼上的二位前辈,我试试

#15


#12 楼提供代码基本能解决楼主的问题
 我这里也有个例子,不过是用win32开发的
http://www.codeproject.com/KB/winsdk/Win32AutoCompleteComboBox.aspx

#16


刚刚再修改一下,这个应该满足你的要求了。阿弥陀佛! ^-^
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);
}

#17


顶一个~

#18


#16楼  jacky_qiu 兄,非常感谢你的代码,但还有一个问题,就是我想要编辑框里的输入项是按顺序查找的,不是如果列表框里有包含这个字符就匹配的,例如我输入a,列表框会匹配a****,而不是***a*,如果首字母没有的a的话,就不进行匹配,这样好改么?

#19


c++不会啊

#20


#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);

#21


引用 20 楼 wfonly 的回复:
#16楼 我根据你的程序和我之前那部分程序,修改成下面一个,但是就是不能再列表框里高亮显示,这是为什么啊
BOOL CAutoCompleteComboBox::OnCommand(WPARAM wParam, LPARAM lParam) 
{
// TODO: Add your specialized code here and/or call the base class

  i……

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
  最好能改成模糊匹配.
   

#22


功能基本可以实现了,谢谢各位前辈的帮助,还有个小问题,如果继续输入时在列表框找不到匹配项,那么如何使已产生的蓝色高亮条去掉呢?

#23


引用 22 楼 wfonly 的回复:
功能基本可以实现了,谢谢各位前辈的帮助,还有个小问题,如果继续输入时在列表框找不到匹配项,那么如何使已产生的蓝色高亮条去掉呢?


去掉蓝条:
 SetCurSel(-1);

#24


引用 23 楼 gameslq 的回复:
引用 22 楼 wfonly 的回复:

去掉蓝条:
SetCurSel(-1);


这样的话是不是就把编辑框里的已输入部分都清除了就

#25


楼上高手已经帮你解决了。愿一切顺利!。

#26


再次非常谢谢jacky_qiu , gameslq 二位前辈的帮助,现在已经可以完美实现想要的功能了,同样祝愿二位一切顺利!

#1


如果选中的话就是SetSel

#2


麻烦能不能写写代码呀,在下菜鸟一个

#3


upup

#4


void CSuperComboBox::OnEditchange() 
{
// TODO: Add your control notification handler code here
ShowDropDown();//这个没问题
// SetCurSel(1);//这个不是你要的,你想叫匹配项变蓝色,对吧
}

#5


是的,列表框下拉后匹配项变成蓝色

#6


像是VC6“help”-》“index”那样的东西吧,要费点劲的。

#7


上面那些代码已经可以实现查询了,现在就是想下拉和高亮显示

#8


这个你可以自己用CComoboBox+CListBox来解决。。。当在CComboBox的编辑框中输入的时候,在对应的位置上ShowWindow(SW_SHOW);来显示CListBox

#9


引用 8 楼 visualeleven 的回复:
这个你可以自己用CComoboBox+CListBox来解决。。。当在CComboBox的编辑框中输入的时候,在对应的位置上ShowWindow(SW_SHOW);来显示CListBox


可以麻烦写些代码吗,谢谢了

#10


不如把Combo去掉,直接用edit+list(=Combo)

#11


//.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);
}


#12


这里有个例子以前网上下载的,可以实现你的要求,但使用了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

#13


我把#12楼的下载看了看,不错,不过还是有问题,如“点击Combo”-》显示list》输入a》list选择“aaaaa”》“点击list的aaaaa”》list消失,再到edit中改变“aaaaa”为‘a’》list不再显示。。。

#14


感谢楼上的二位前辈,我试试

#15


#12 楼提供代码基本能解决楼主的问题
 我这里也有个例子,不过是用win32开发的
http://www.codeproject.com/KB/winsdk/Win32AutoCompleteComboBox.aspx

#16


刚刚再修改一下,这个应该满足你的要求了。阿弥陀佛! ^-^
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);
}

#17


顶一个~

#18


#16楼  jacky_qiu 兄,非常感谢你的代码,但还有一个问题,就是我想要编辑框里的输入项是按顺序查找的,不是如果列表框里有包含这个字符就匹配的,例如我输入a,列表框会匹配a****,而不是***a*,如果首字母没有的a的话,就不进行匹配,这样好改么?

#19


c++不会啊

#20


#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);

#21


引用 20 楼 wfonly 的回复:
#16楼 我根据你的程序和我之前那部分程序,修改成下面一个,但是就是不能再列表框里高亮显示,这是为什么啊
BOOL CAutoCompleteComboBox::OnCommand(WPARAM wParam, LPARAM lParam) 
{
// TODO: Add your specialized code here and/or call the base class

  i……

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
  最好能改成模糊匹配.
   

#22


功能基本可以实现了,谢谢各位前辈的帮助,还有个小问题,如果继续输入时在列表框找不到匹配项,那么如何使已产生的蓝色高亮条去掉呢?

#23


引用 22 楼 wfonly 的回复:
功能基本可以实现了,谢谢各位前辈的帮助,还有个小问题,如果继续输入时在列表框找不到匹配项,那么如何使已产生的蓝色高亮条去掉呢?


去掉蓝条:
 SetCurSel(-1);

#24


引用 23 楼 gameslq 的回复:
引用 22 楼 wfonly 的回复:

去掉蓝条:
SetCurSel(-1);


这样的话是不是就把编辑框里的已输入部分都清除了就

#25


楼上高手已经帮你解决了。愿一切顺利!。

#26


再次非常谢谢jacky_qiu , gameslq 二位前辈的帮助,现在已经可以完美实现想要的功能了,同样祝愿二位一切顺利!