wangchao.org
添加收藏 | 博客
 
购物视频论坛IT业界自然风光美女图片王朝网络小游戏BT下载生活百科编程设计手机图铃小说
 
笑话 | 水库 | 娱乐 | 体育 | 英语 | 宠物 | 美食 | 旅游 | 养生 | 手机 | 数码 | 汽车 | 珠宝 | 美容 | 装修 | 厨房 | 科普 | 动物 | 植物 | 影音 | 百科 | 知道 | 词典
  
 
 您好! 您现在位于: 王朝网络 → 编程设计 → 《响应AutoComplete下拉列表的选择事件返回上一页 
 
1楼 

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

  网上购物、在线购物、购物搜索 欢迎光临本站购买图书、影视、音乐、数码、百货,手机等商品。

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

  这样贴心的功能自然为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中似乎并没有相关的文档。
  3、SPY++
  我们马上想到用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的后台工作设置为我们所选择的列表项了,因此对于该消息的wParam和lParam的意义我们也可以不去深究。
  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下拉列表的选择事件

关键字:SHAutoComplete 1、SHAutoComplete简介 Shlwapi.dll是微软提供的一个轻量级外壳工具函数库(Shell Lightweight Utility Functions),它提供了一些比较常用的函数,用以处理调色板、路径(如《[url=http://blog.csdn.net/cathyeagle/archive/2004/09/16/106248.aspx]Secrets in ShlWapi.Dll[/url]》中提到的PathCompactPath函数)、注册表、字符串等。从5.0版本(随Internet Explorer 5推出)开始,shlwapi.dll还提供了一个函数SHAutoComplete,它使得编辑框控件(如Edit、ComboBox)具有被称为“自动完成”的功能,即当用户在编辑框中输入的时候自动弹出一个非激活的窗口,为用户输入提供建议。如我们在Internet Explorer的地址栏输入“google”,如果系统记录了以前输入过“www.google.com”,则地址栏下方会显示出建议的网址。 [img]http://blog.csdn.net/images/blog_csdn_net/cathyeagle/32965/o_AutoComplete.jpg[/img] 这样贴心的功能自然为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中似乎并没有相关的文档。 3、SPY++ 我们马上想到用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函数在运行时向系统注册的消息(参见《[url=http://blog.csdn.net/CathyEagle/archive/2004/08/09/69622.aspx]Windows通知栏图标高级编程概述[/url]》和《[url=http://blog.csdn.net/CathyEagle/archive/2004/08/09/69627.aspx]具有自动恢复功能的通知栏图标控件[/url]》),从其字面意思来看正是我们想要的。我们注意到Edit在接收到该消息之前还接收到了WM_SETTEXT消息,即此刻Edit中的文字已经被SHAutoComplete的后台工作设置为我们所选择的列表项了,因此对于该消息的wParam和lParam的意义我们也可以不去深究。 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: [url=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/Shell/reference/shlwapi/version/shautocomplete.asp]SHAutoComplete Function[/url] 引用地址:《[url=http://blog.csdn.net/CathyEagle/archive/2006/02/21/605054.aspx]响应AutoComplete下拉列表的选择事件[/url]》

 
标签: AutoComplete  下拉  事件  列表  响应  选择  
 
您可以将本页贴到其他网站
UBB代码HTML代码
 
 
 
 
 
 
 更多内容
 ·整理电脑,又挖到一个隐身的进程 ·[译]理解为什么防火墙聊胜于无 ·RFID的现状与今后动向 - 序言 ·[B原创] Arm/x86结构体gcc内存边
 ·2006年3GSM全球大会10佳手机   ·驳斥一些不看好Flash的观点 ·互联网推广中被滥用了的技术 ·怎样成为一个Flash Lite Develop
 ·Google三架马车为何绝口不谈公司 ·怎样成为一个Flash Lite Develop ·广东省-IT公司红黑榜排名 ·学习ARM开发(19)
 ·2月份《程序员》杂志之10佳技术B ·NET Pet Shop 的设计模式与体系结 ·一个DataGrid多次绑定不同数据的 ·用Mind Map 激发你的记忆潜能
 ·某"一卡通"系统的架构 ·超越浏览器 迎接Smart Client ·谈AJAX的安全性及AJAX安全隐患 ·2006的年度技术和框架?
 ·Get Microsoft Office Live Beta ·[原创]善用google的what is ·边界跟踪 边缘检测 边缘连接 ·获取cpu序列号,硬盘ID,网卡MAC地
 
 
最新评论  点此查看所有评论
 
 
 
 
发表评论(支持UBB码)


验证码:  
 
 
 
© 2005- 王朝网络 版权所有