张硕(CathyEagle)的专栏

      ——朝闻道,夕死可矣。

用户操作
[即时聊天] [发私信] [加为好友]
张硕ID:CathyEagle
204950次访问,排名349好友0人,关注者5
CathyEagle的文章
原创 57 篇
翻译 0 篇
转载 0 篇
评论 328 篇
CathyEagle的公告
eagleboost@21cn.com

声明:本专栏之文章及照片,除特别注明外均为本人原创,如有转载,敬请注明出处。若需商业用途,请与本人联系。

Google

最近评论
renhit:实在惭愧,没明白这里:GetActiveWebBrowserPtr返回活动的浏览器IWebBrowser2接口指针

GetActiveWebBrowserPtr这个函数该怎么实现?不是微软提供的吧?

谢谢
wangzivc2004:非常感谢楼主, 帮了我大忙了.
由于自己不才, 没有看过Hook方面的知识, 虽然知道MFC也是利用Hook模拟模态对话框的, 但是自己就是不知咋办. 现在老大让我用WTL做东西, 发现那里面模态对话框恶心的连键盘消息都无法响应, 最终还是无意间发现这篇经典的文章.

再次感谢
CathyEagle:看了老兄的溢美之词,汗流浃背in……
sunhui:昨天聊到深夜,决定今天来拜读大作,果然精彩!非常佩服你的精细,期待你的MiExplorer早日面世……,很羡慕你的文档写作能力。
CathyEagle:参考下面的代码:
LPDISPATCH glpDisp = NULL; // global LPDISPATCH, can also
// be of class scope

// NavigateComplete2 event
void CWebbrDlg::OnNavigateComplete……
文章分类
收藏
    相册
    恋之风景
    我的生活
    C++
    C++ Templates 中文
    Effective STL 中文
    周星星之Blog
    Delphi
    Delphi窑洞
    Torry.net
    大富翁论坛
    源码空间
    绝好的Delphi Tips
    Java
    !Java
    Misc
    SourceForge.org
    Think in Patterns 中文
    ZoCSoft.com
    阿甘的家
    友情链接
    Stanley_Xu 的专栏
    编程手札
    综合
    CodeGuru
    The Code Project
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 响应AutoComplete下拉列表的选择事件收藏

    新一篇:  Internet Explorer 编程简述(十)响应来自HTML Element的事件通知——几个好用的类 | 旧一篇: Internet Explorer 编程简述(九)在自己的浏览器中嵌入Google工具条

     

    关键字: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下拉列表的选择事件

    发表于 @ 2006年02月21日 23:23:00|评论(loading...)|编辑

    新一篇:  Internet Explorer 编程简述(十)响应来自HTML Element的事件通知——几个好用的类 | 旧一篇: Internet Explorer 编程简述(九)在自己的浏览器中嵌入Google工具条

    评论:没有评论。

    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © CathyEagle