响应AutoComplete下拉列表的选择事件

原创 2006年02月21日 23:23:00
 

关键字:SHAutoComplete

 

1SHAutoComplete简介

Shlwapi.dll是微软提供的一个轻量级外壳工具函数库(Shell Lightweight Utility Functions),它提供了一些比较常用的函数,用以处理调色板、路径(如《Secrets in ShlWapi.Dll中提到的PathCompactPath函数)、注册表、字符串等。从5.0版本(随Internet Explorer 5推出)开始,shlwapi.dll还提供了一个函数SHAutoComplete,它使得编辑框控件(如EditComboBox)具有被称为“自动完成”的功能,即当用户在编辑框中输入的时候自动弹出一个非激活的窗口,为用户输入提供建议。如我们在Internet Explorer的地址栏输入“google”,如果系统记录了以前输入过“www.google.com”,则地址栏下方会显示出建议的网址。

 

AutoComplete

 

这样贴心的功能自然为IE 5赢得市场提供了帮助,而对开发人员来说,如果能够毫不费力地为自己的程序添加这样的功能则是再好不过。SHAutoComplete就是最直接而简单的选择。下面的代码演示了如何调用SHAutoComplete函数为某个Edit控件添加自动完成的功能:

 

typedef HRESULT (CALLBACK* LPFNDLLFUNC)(HWND ,DWORD);

HINSTANCE hIns = LoadLibrary(_T("shlwapi.dll"));

if( hIns != NULL )

{

LPFNDLLFUNC lpfnDllFunc = (LPFNDLLFUNC)GetProcAddress(hIns, "SHAutoComplete");

if( lpfnDllFunc != NULL )

{

lpfnDllFunc(m_wndAddressBar.m_hWnd, SHACF_AUTOAPPEND_FORCE_ON |

SHACF_AUTOSUGGEST_FORCE_ON | SHACF_URLALL);

}

FreeLibrary(hIns);

}

 

从微软的习惯来说,这种对用户来说极为有用的功能不会只提供这样一个简单的函数就完事。事实上,SHAutoComplete只完成系统默认实现的功能,开发人员如果需要自定义以提供更强功能的话则可通过实现IAutoComplete接口以及IAutoComplete2接口来完成(在Windows XP中还提供了IAutoCompleteDropDown接口用以控制上图中那个下拉列表窗口的状态)。

 

2、问题的提出

我们知道,当用户在ComboBox控件的下拉框中用鼠标点击某个列表项或在列表项上按回车键时,ComboBox的父窗口会通过WM_COMMAND消息接收到一个CBN_SELENDOK通知,从而可以知道用户选择了那一个列表项并进行处理,在VC++中类似这样:

 

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)

ON_CBN_SELENDOK(ID_ADDRESSBOX, &CMainFrame::OnSelAddress)

......

END_MESSAGE_MAP()

 

void CMainFrame::OnSelAddress()

{

CString str = m_wndAddressBar.GetLBAddress();

...... //处理用户的选择

}

 

自然而然地,对于SHAutoComplete提供的下拉框,我们也希望有这样的通知,但MSDN中似乎并没有相关的文档。

 

3SPY++

我们马上想到用Spy++来跟踪消息。以IE的地址栏为例,当我们在SHAutoComplete的下拉框中点击(按回车键有同样的效果)“http://www.google.com 这个列表项时,地址栏中的Edit的消息踪迹如下所示:

 

<00589> 001B0BF4 S WM_SETTEXT lpsz:0013D074 ("http://www.google.com")

......

<00606> 001B0BF4 R EM_SETSEL

<00607> 001B0BF4 S message:0xC2B6 [Registered:"AC_ItemActivate"] wParam:00000000 lParam:0013D494

<00608> 001B0BF4 R message:0xC2B6 [Registered:"AC_ItemActivate"] lResult:00000000

<00609> 001B0BF4 S WM_KEYDOWN nVirtKey:VK_RETURN cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0

......

 

包含Registered:"AC_ItemActivate"的这一行立刻引起了我们的注意。这是一个用RegisterWindowMessage函数在运行时向系统注册的消息(参见Windows通知栏图标高级编程概述具有自动恢复功能的通知栏图标控件),从其字面意思来看正是我们想要的。我们注意到Edit在接收到该消息之前还接收到了WM_SETTEXT消息,即此刻Edit中的文字已经被SHAutoComplete的后台工作设置为我们所选择的列表项了,因此对于该消息的wParamlParam的意义我们也可以不去深究。

 

4、问题解决

下面是一个简单的解决方案:

 

// CACEditSubclassWnd

 

class CACEditSubclassWnd : public CWnd

{

DECLARE_DYNAMIC(CACEditSubclassWnd)

static const UINT m_nAcItemActivateMsg;

//用来保存向系统注册的消息

public:

CACEditSubclassWnd(){};

virtual ~CACEditSubclassWnd(){};

 

protected:

LRESULT OnAcItemActivate(WPARAM wParam, LPARAM lParam);

DECLARE_MESSAGE_MAP()

};

 

// CACEditSubclassWnd

// 向系统注册我们需要的消息

const UINT CACEditSubclassWnd::m_nAcItemActivateMsg = ::RegisterWindowMessage(_T("AC_ItemActivate"));

 

IMPLEMENT_DYNAMIC(CACEditSubclassWnd, CWnd)

 

BEGIN_MESSAGE_MAP(CACEditSubclassWnd, CWnd)

ON_REGISTERED_MESSAGE(CACEditSubclassWnd::m_nAcItemActivateMsg, &CACEditSubclassWnd::OnAcItemActivate)

END_MESSAGE_MAP()

 

// CACEditSubclassWnd message handlers

LRESULT CACEditSubclassWnd::OnAcItemActivate(WPARAM wParam, LPARAM lParam)

{

AfxGetMainWnd()->SendMessage(WM_COMMAND, MAKEWPARAM(LOWORD(ACCBN_SELENDOK), 0x0), 0);

//ACCBN_SELENDOK是我们自定义的通知

return 0L;

}

 

假设CUrlAddressCombo是一个地址栏类,则为其声明一个CACEditSubclassWnd类型的成员,并在适当的位置(如Init成员函数中)子类化Edit控件。

 

class CUrlAddressCombo : public CComboBoxEx

{

private:

CACEditSubclassWnd m_ACEditSubclassWnd;

......

}

void CUrlAddressCombo::Init(void)

{

m_ACEditSubclassWnd.SubclassWindow( GetEditCtrl()->m_hWnd );

}

而在CMainFrame中可以这样实现:

 

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)

ON_COMMAND(ACCBN_SELENDOK, &CMainFrame::OnACSelEndOk)

......

END_MESSAGE_MAP()

 

void CMainFrame::OnACSelEndOk()

{

CString strAddr;

m_wndAddressBar.GetEditCtrl()->GetWindowText(strAddr);

...... //处理用户的选择

}

 

非常简单,不是吗?

5、参考文献

MSDN: SHAutoComplete Function

引用地址:《响应AutoComplete下拉列表的选择事件

angularjs-搜索框下拉列表

最近参考了很多大型互联网公司的搜索框都会预推一些热门的关键词作为一个搜索选择,用户可以快速找到关键词,然后搜索点击进入。下面是我最近利用空余时间写的一个demo: 下面将利用an...
  • u012979009
  • u012979009
  • 2017年03月14日 17:11
  • 1014

Jquery autocomplete 注意的一点破事

前面使用Jquery autocomplete对输入框进行自动填充代码编写,如果远程url获取的数据为单纯的string返回的json数据,那么就可以正常显示,如果是返回的复杂的json数据就无法正常...
  • hack8
  • hack8
  • 2015年11月18日 22:48
  • 6969

单击触发jquery.autocomplete的两种方法

jquery.autocomplete的参数 minChars设置为0时,默认要双击才会触发jquery.autocomplete,如果想要单击触发的话,得进行一定的处理才行.下面讲下我知道的单击触发...
  • smeyou
  • smeyou
  • 2012年08月31日 11:16
  • 7449

JQuery autocomplete选中某项后触发事件

为选中后触发的事件。item为选中的相。 例如,我们可以在选中后直接跳转页面: var data = [ {text:'Link A', http://'/page1'}, {text:'Link...
  • tanghier
  • tanghier
  • 2013年01月06日 11:57
  • 3267

懒人活用JQuery.Autocomplete实现Select触发事件和结果定制

工作当中用到了JQuery 的Autocomplete插件,但是遇到的是非常规使用的问题。   其一是下拉菜单的显示和填入文本框的结果要求的字符串不一样,即显示用户名,所属部门,但是填入文本框里的...
  • Loulley123
  • Loulley123
  • 2011年10月11日 15:33
  • 7307

懒人活用JQuery.Autocomplete实现Select触发事件和结果定制

jQuery autocomplete, 结果定制, 触发事件, 回调事件
  • batman9956
  • batman9956
  • 2010年08月17日 03:42
  • 11264

angularjs实现下拉列表的选中事件

自动发放
  • han1196639488
  • han1196639488
  • 2017年03月02日 16:53
  • 1785

jquery autocomplete 怎样实现动态绑定

怀疑药品   药品名称:                            {$v.m_name}              --...
  • woshini_nishiwo
  • woshini_nishiwo
  • 2015年03月17日 09:59
  • 988

Combox控件下拉选择不同值触发的动作响应

项目中需要根据combox控件下拉列表选择不同的值,然后能触发相应的动作。比如我的项目中,通过combox空间的下拉列表选择不同的C盘,D盘,E盘,F盘,然后能在list控件中把各个盘符的文件目录列出...
  • u013051748
  • u013051748
  • 2015年05月08日 12:19
  • 3033

【BootStrap】关于Select下拉框选择触发事件以及扩展

转载请注明出处:http://blog.csdn.net/qq_26525215 本文源自【大学之旅_谙忆的博客】 Select下拉框的问题,想在选择一个选项后,前台显示做出变动,并且知道选择的是第几...
  • qq_26525215
  • qq_26525215
  • 2016年11月22日 00:47
  • 5397
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:响应AutoComplete下拉列表的选择事件
举报原因:
原因补充:

(最多只允许输入30个字)