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);//这个不是你要的,你想叫匹配项变蓝色,对吧
}
{
// 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
可以麻烦写些代码吗,谢谢了
#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);
}
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
这个是原来作者的写的,感谢他。
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
我这里也有个例子,不过是用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);
}
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);
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
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
去掉蓝条:
SetCurSel(-1);
#24
这样的话是不是就把编辑框里的已输入部分都清除了就
#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);//这个不是你要的,你想叫匹配项变蓝色,对吧
}
{
// 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
可以麻烦写些代码吗,谢谢了
#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);
}
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
这个是原来作者的写的,感谢他。
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
我这里也有个例子,不过是用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);
}
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);
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
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
去掉蓝条:
SetCurSel(-1);
#24
这样的话是不是就把编辑框里的已输入部分都清除了就
#25
楼上高手已经帮你解决了。愿一切顺利!。
#26
再次非常谢谢jacky_qiu , gameslq 二位前辈的帮助,现在已经可以完美实现想要的功能了,同样祝愿二位一切顺利!