天天看点

C++开发BHO之HelloWorld原文:



原文:

http://msdn.microsoft.com/en-us/library/bb250489(v=vs.85).aspx

开发工具VS2010。

步骤如图:

C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:
C++开发BHO之HelloWorld原文:

生成的HelloWorldBHO.h的代码如下:

[cpp] view plain copy print ?

  1. // HelloWorldBHO.h : CHelloWorldBHO 的声明  
  2. #pragma once  
  3. #include "resource.h"       // 主符号  
  4. #include "HelloWorld_i.h"  
  5. #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)  
  6. #error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"  
  7. #endif  
  8. using namespace ATL;  
  9. // CHelloWorldBHO  
  10. class ATL_NO_VTABLE CHelloWorldBHO :  
  11.     public CComObjectRootEx<CComSingleThreadModel>,  
  12.     public CComCoClass<CHelloWorldBHO, &CLSID_HelloWorldBHO>,  
  13.     public IObjectWithSiteImpl<CHelloWorldBHO>,  
  14.     public IDispatchImpl<IHelloWorldBHO, &IID_IHelloWorldBHO, &LIBID_HelloWorldLib,  1,  0>  
  15. {  
  16. public:  
  17.     CHelloWorldBHO()  
  18.     {  
  19.     }  
  20. DECLARE_REGISTRY_RESOURCEID(IDR_HELLOWORLDBHO)  
  21. DECLARE_NOT_AGGREGATABLE(CHelloWorldBHO)  
  22. BEGIN_COM_MAP(CHelloWorldBHO)  
  23.     COM_INTERFACE_ENTRY(IHelloWorldBHO)  
  24.     COM_INTERFACE_ENTRY(IDispatch)  
  25.     COM_INTERFACE_ENTRY(IObjectWithSite)  
  26. END_COM_MAP()  
  27.     DECLARE_PROTECT_FINAL_CONSTRUCT()  
  28.     HRESULT FinalConstruct()  
  29.     {  
  30.         return S_OK;  
  31.     }  
  32.     void FinalRelease()  
  33.     {  
  34.     }  
  35. public:  
  36. };  
  37. OBJECT_ENTRY_AUTO(__uuidof(HelloWorldBHO), CHelloWorldBHO)  
// HelloWorldBHO.h : CHelloWorldBHO 的声明

#pragma once
#include "resource.h"       // 主符号



#include "HelloWorld_i.h"



#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"
#endif

using namespace ATL;


// CHelloWorldBHO

class ATL_NO_VTABLE CHelloWorldBHO :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CHelloWorldBHO, &CLSID_HelloWorldBHO>,
	public IObjectWithSiteImpl<CHelloWorldBHO>,
	public IDispatchImpl<IHelloWorldBHO, &IID_IHelloWorldBHO, &LIBID_HelloWorldLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
	CHelloWorldBHO()
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_HELLOWORLDBHO)

DECLARE_NOT_AGGREGATABLE(CHelloWorldBHO)

BEGIN_COM_MAP(CHelloWorldBHO)
	COM_INTERFACE_ENTRY(IHelloWorldBHO)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()



	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}

public:



};

OBJECT_ENTRY_AUTO(__uuidof(HelloWorldBHO), CHelloWorldBHO)
           

HelloWorldBHO.cpp的代码如下:

[cpp] view plain copy print ?

  1. // HelloWorldBHO.cpp : CHelloWorldBHO 的实现  
  2. #include "stdafx.h"  
  3. #include "HelloWorldBHO.h"  
  4. // CHelloWorldBHO  
// HelloWorldBHO.cpp : CHelloWorldBHO 的实现

#include "stdafx.h"
#include "HelloWorldBHO.h"


// CHelloWorldBHO
           

HelloWorld.cpp的代码如下:

[cpp] view plain copy print ?

  1. // HelloWorld.cpp : DLL 导出的实现。  
  2. #include "stdafx.h"  
  3. #include "resource.h"  
  4. #include "HelloWorld_i.h"  
  5. #include "dllmain.h"  
  6. // 用于确定 DLL 是否可由 OLE 卸载。  
  7. STDAPI DllCanUnloadNow(void)  
  8. {  
  9.             return _AtlModule.DllCanUnloadNow();  
  10.     }  
  11. // 返回一个类工厂以创建所请求类型的对象。  
  12. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)  
  13. {  
  14.         return _AtlModule.DllGetClassObject(rclsid, riid, ppv);  
  15. }  
  16. // DllRegisterServer - 在系统注册表中添加项。  
  17. STDAPI DllRegisterServer(void)  
  18. {  
  19.     // 注册对象、类型库和类型库中的所有接口  
  20.     HRESULT hr = _AtlModule.DllRegisterServer();  
  21.         return hr;  
  22. }  
  23. // DllUnregisterServer - 在系统注册表中移除项。  
  24. STDAPI DllUnregisterServer(void)  
  25. {  
  26.     HRESULT hr = _AtlModule.DllUnregisterServer();  
  27.         return hr;  
  28. }  
  29. // DllInstall - 按用户和计算机在系统注册表中逐一添加/移除项。  
  30. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)  
  31. {  
  32.     HRESULT hr = E_FAIL;  
  33.     static const wchar_t szUserSwitch[] = L"user";  
  34.     if (pszCmdLine != NULL)  
  35.     {  
  36.         if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)  
  37.         {  
  38.             ATL::AtlSetPerUserRegistration(true);  
  39.         }  
  40.     }  
  41.     if (bInstall)  
  42.     {     
  43.         hr = DllRegisterServer();  
  44.         if (FAILED(hr))  
  45.         {  
  46.             DllUnregisterServer();  
  47.         }  
  48.     }  
  49.     else  
  50.     {  
  51.         hr = DllUnregisterServer();  
  52.     }  
  53.     return hr;  
  54. }  
// HelloWorld.cpp : DLL 导出的实现。


#include "stdafx.h"
#include "resource.h"
#include "HelloWorld_i.h"
#include "dllmain.h"


// 用于确定 DLL 是否可由 OLE 卸载。
STDAPI DllCanUnloadNow(void)
{
			return _AtlModule.DllCanUnloadNow();
	}

// 返回一个类工厂以创建所请求类型的对象。
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
		return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
}

// DllRegisterServer - 在系统注册表中添加项。
STDAPI DllRegisterServer(void)
{
	// 注册对象、类型库和类型库中的所有接口
	HRESULT hr = _AtlModule.DllRegisterServer();
		return hr;
}

// DllUnregisterServer - 在系统注册表中移除项。
STDAPI DllUnregisterServer(void)
{
	HRESULT hr = _AtlModule.DllUnregisterServer();
		return hr;
}

// DllInstall - 按用户和计算机在系统注册表中逐一添加/移除项。
STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
{
	HRESULT hr = E_FAIL;
	static const wchar_t szUserSwitch[] = L"user";

	if (pszCmdLine != NULL)
	{
		if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
		{
			ATL::AtlSetPerUserRegistration(true);
		}
	}

	if (bInstall)
	{	
		hr = DllRegisterServer();
		if (FAILED(hr))
		{
			DllUnregisterServer();
		}
	}
	else
	{
		hr = DllUnregisterServer();
	}

	return hr;
}

           

dllmain.cpp的代码如下:

[cpp] view plain copy print ?

  1. // dllmain.cpp : DllMain 的实现。  
  2. #include "stdafx.h"  
  3. #include "resource.h"  
  4. #include "HelloWorld_i.h"  
  5. #include "dllmain.h"  
  6. CHelloWorldModule _AtlModule;  
  7. // DLL 入口点  
  8. extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)  
  9. {  
  10.     hInstance;  
  11.     return _AtlModule.DllMain(dwReason, lpReserved);   
  12. }  
// dllmain.cpp : DllMain 的实现。

#include "stdafx.h"
#include "resource.h"
#include "HelloWorld_i.h"
#include "dllmain.h"

CHelloWorldModule _AtlModule;

// DLL 入口点
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
	hInstance;
	return _AtlModule.DllMain(dwReason, lpReserved); 
}
           

HelloWorld.rgs的内容如下:

[plain] view plain copy print ?

  1. HKCR  
  2. {  
  3. }  
HKCR
{
}
           

HelloWorldBHO.rgs的内容如下:

[plain] view plain copy print ?

  1. HKCR  
  2. {  
  3.     NoRemove CLSID  
  4.     {  
  5.         ForceRemove {22024CC8-9043-49C7-AC80-A803A2912BF6} = s 'HelloWorldBHO Class'  
  6.         {  
  7.             ForceRemove Programmable  
  8.             InprocServer32 = s '%MODULE%'  
  9.             {  
  10.                 val ThreadingModel = s 'Apartment'  
  11.             }  
  12.             TypeLib = s '{D05D8B0F-8126-4FE2-BC3D-D5A5248E7025}'  
  13.             Version = s '1.0'  
  14.         }  
  15.     }  
  16. }  
HKCR
{
	NoRemove CLSID
	{
		ForceRemove {22024CC8-9043-49C7-AC80-A803A2912BF6} = s 'HelloWorldBHO Class'
		{
			ForceRemove Programmable
			InprocServer32 = s '%MODULE%'
			{
				val ThreadingModel = s 'Apartment'
			}
			TypeLib = s '{D05D8B0F-8126-4FE2-BC3D-D5A5248E7025}'
			Version = s '1.0'
		}
	}
}
           

HelloWorld.idl的内容:

[plain] view plain copy print ?

  1. // HelloWorld.idl : HelloWorld 的 IDL 源  
  2. //  
  3. // 此文件将由 MIDL 工具处理以  
  4. // 产生类型库(HelloWorld.tlb)和封送处理代码。  
  5. import "oaidl.idl";  
  6. import "ocidl.idl";  
  7. [  
  8.     object,  
  9.     uuid(9C44C518-EEBE-4126-B368-5B901F840255),  
  10.     dual,  
  11.     nonextensible,  
  12.     pointer_default(unique)  
  13. ]  
  14. interface IHelloWorldBHO : IDispatch{  
  15. };  
  16. [  
  17.     uuid(D05D8B0F-8126-4FE2-BC3D-D5A5248E7025),  
  18.     version(1.0),  
  19. ]  
  20. library HelloWorldLib  
  21. {  
  22.     importlib("stdole2.tlb");  
  23.     [  
  24.         uuid(22024CC8-9043-49C7-AC80-A803A2912BF6)        
  25.     ]  
  26.     coclass HelloWorldBHO  
  27.     {  
  28.         [default] interface IHelloWorldBHO;  
  29.     };  
  30. };  
// HelloWorld.idl : HelloWorld 的 IDL 源
//

// 此文件将由 MIDL 工具处理以
// 产生类型库(HelloWorld.tlb)和封送处理代码。

import "oaidl.idl";
import "ocidl.idl";

[
	object,
	uuid(9C44C518-EEBE-4126-B368-5B901F840255),
	dual,
	nonextensible,
	pointer_default(unique)
]
interface IHelloWorldBHO : IDispatch{
};
[
	uuid(D05D8B0F-8126-4FE2-BC3D-D5A5248E7025),
	version(1.0),
]
library HelloWorldLib
{
	importlib("stdole2.tlb");
	[
		uuid(22024CC8-9043-49C7-AC80-A803A2912BF6)		
	]
	coclass HelloWorldBHO
	{
		[default] interface IHelloWorldBHO;
	};
};
           

HelloWorld.idl中的CLSID是22024CC8-9043-49C7-AC80-A803A2912BF6

其他的文件,暂时不重要。

修改HelloWorldBHO.h:

1、增加头文件

[cpp] view plain copy print ?

  1. #include <shlguid.h>  
  2. #include <exdispid.h>  
#include <shlguid.h>
#include <exdispid.h>
           

2、增加一个公有的SetSite方法:

[cpp] view plain copy print ?

  1. public:  
  2.     STDMETHOD(SetSite)(IUnknown *pUnkSite);  
public:

	STDMETHOD(SetSite)(IUnknown *pUnkSite);
           

3、增加私有的成员变量:

[cpp] view plain copy print ?

  1. private:  
  2.     CComPtr<IWebBrowser2>  m_spWebBrowser;  
  3.     BOOL m_fAdvised;  
private:

    CComPtr<IWebBrowser2>  m_spWebBrowser;
	BOOL m_fAdvised;
           

4、多继承一个类:

[cpp] view plain copy print ?

  1. public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>  
public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
           

5、增加公有的方法OnDocumentComplete:

[cpp] view plain copy print ?

  1. BEGIN_SINK_MAP(CHelloWorldBHO)  
  2.     SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)  
  3. END_SINK_MAP()  
  4.     // DWebBrowserEvents2  
  5.     void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);  
BEGIN_SINK_MAP(CHelloWorldBHO)
    SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()

    // DWebBrowserEvents2
    void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);
           

修改HelloWorldBHO.cpp,实现那两个方法:

[cpp] view plain copy print ?

  1. STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite)  
  2. {  
  3.     if (pUnkSite != NULL)  
  4.     {  
  5.         // Cache the pointer to IWebBrowser2.  
  6.         HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);  
  7.         if (SUCCEEDED(hr))  
  8.         {  
  9.             // Register to sink events from DWebBrowserEvents2.  
  10.             hr = DispEventAdvise(m_spWebBrowser);  
  11.             if (SUCCEEDED(hr))  
  12.             {  
  13.                 m_fAdvised = TRUE;  
  14.             }  
  15.         }  
  16.     }  
  17.     else  
  18.     {  
  19.         // Unregister event sink.  
  20.         if (m_fAdvised)  
  21.         {  
  22.             DispEventUnadvise(m_spWebBrowser);  
  23.             m_fAdvised = FALSE;  
  24.         }  
  25.         // Release cached pointers and other resources here.  
  26.         m_spWebBrowser.Release();  
  27.     }  
  28.     // Call base class implementation.  
  29.     return IObjectWithSiteImpl<CHelloWorldBHO>::SetSite(pUnkSite);  
  30. }  
  31. void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)  
  32. {  
  33.     // Retrieve the top-level window from the site.  
  34.     HWND hwnd;  
  35.     HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd);  
  36.     if (SUCCEEDED(hr))  
  37.     {  
  38.         // Output a message box when page is loaded.  
  39.         MessageBox(hwnd, L"Hello World!", L"BHO", MB_OK);  
  40.     }  
  41. }  
STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite)
{
    if (pUnkSite != NULL)
    {
        // Cache the pointer to IWebBrowser2.
        HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
        if (SUCCEEDED(hr))
        {
            // Register to sink events from DWebBrowserEvents2.
            hr = DispEventAdvise(m_spWebBrowser);
            if (SUCCEEDED(hr))
            {
                m_fAdvised = TRUE;
            }
        }
    }
    else
    {
        // Unregister event sink.
        if (m_fAdvised)
        {
            DispEventUnadvise(m_spWebBrowser);
            m_fAdvised = FALSE;
        }

        // Release cached pointers and other resources here.
        m_spWebBrowser.Release();
    }

    // Call base class implementation.
    return IObjectWithSiteImpl<CHelloWorldBHO>::SetSite(pUnkSite);
}

void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
    // Retrieve the top-level window from the site.
    HWND hwnd;
    HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd);
    if (SUCCEEDED(hr))
    {
        // Output a message box when page is loaded.
        MessageBox(hwnd, L"Hello World!", L"BHO", MB_OK);
    }
}
           

dllmain.cpp的DllMain修改成:

[cpp] view plain copy print ?

  1. extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)  
  2. {  
  3.     if (dwReason == DLL_PROCESS_ATTACH)  
  4.     {  
  5.         DisableThreadLibraryCalls(hInstance);  
  6.     }  
  7.     return _AtlModule.DllMain(dwReason, lpReserved);   
  8. }  
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hInstance);
    }
    return _AtlModule.DllMain(dwReason, lpReserved); 
}
           

修改HelloWorld.rgs:

修改成:

[plain] view plain copy print ?

  1. HKLM {  
  2.   NoRemove SOFTWARE {  
  3.     NoRemove Microsoft {     
  4.       NoRemove Windows {  
  5.         NoRemove CurrentVersion {  
  6.           NoRemove Explorer {  
  7.             NoRemove 'Browser Helper Objects' {  
  8.               ForceRemove '{D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77}' = s 'HelloWorldBHO' {  
  9.                 val 'NoExplorer' = d '1'  
  10.               }  
  11.             }  
  12.           }  
  13.         }  
  14.       }  
  15.     }  
  16.   }  
  17. }  
HKLM {
  NoRemove SOFTWARE {
    NoRemove Microsoft {   
      NoRemove Windows {
        NoRemove CurrentVersion {
          NoRemove Explorer {
            NoRemove 'Browser Helper Objects' {
              ForceRemove '{D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77}' = s 'HelloWorldBHO' {
                val 'NoExplorer' = d '1'
              }
            }
          }
        }
      }
    }
  }
}
           

其中的{D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77},需要改成HelloWorld.idl中的CLSID,当前文件的CLSID是

{22024CC8-9043-49C7-AC80-A803A2912BF6}

修改完后:

HelloWorldBHO.h:

[cpp] view plain copy print ?

  1. // HelloWorldBHO.h : CHelloWorldBHO 的声明  
  2. #pragma once  
  3. #include "resource.h"       // 主符号  
  4. #include <shlguid.h>  
  5. #include <exdispid.h>  
  6. #include "HelloWorld_i.h"  
  7. #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)  
  8. #error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"  
  9. #endif  
  10. using namespace ATL;  
  11. // CHelloWorldBHO  
  12. class ATL_NO_VTABLE CHelloWorldBHO :  
  13.     public CComObjectRootEx<CComSingleThreadModel>,  
  14.     public CComCoClass<CHelloWorldBHO, &CLSID_HelloWorldBHO>,  
  15.     public IObjectWithSiteImpl<CHelloWorldBHO>,  
  16.     public IDispatchImpl<IHelloWorldBHO, &IID_IHelloWorldBHO, &LIBID_HelloWorldLib,  1,  0>,  
  17.     public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>  
  18. {  
  19. public:  
  20.     CHelloWorldBHO()  
  21.     {  
  22.     }  
  23. DECLARE_REGISTRY_RESOURCEID(IDR_HELLOWORLDBHO)  
  24. DECLARE_NOT_AGGREGATABLE(CHelloWorldBHO)  
  25. BEGIN_COM_MAP(CHelloWorldBHO)  
  26.     COM_INTERFACE_ENTRY(IHelloWorldBHO)  
  27.     COM_INTERFACE_ENTRY(IDispatch)  
  28.     COM_INTERFACE_ENTRY(IObjectWithSite)  
  29. END_COM_MAP()  
  30.     DECLARE_PROTECT_FINAL_CONSTRUCT()  
  31.     HRESULT FinalConstruct()  
  32.     {  
  33.         return S_OK;  
  34.     }  
  35.     void FinalRelease()  
  36.     {  
  37.     }  
  38. public:  
  39.     STDMETHOD(SetSite)(IUnknown *pUnkSite);  
  40. BEGIN_SINK_MAP(CHelloWorldBHO)  
  41.     SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)  
  42. END_SINK_MAP()  
  43.     // DWebBrowserEvents2  
  44.     void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);  
  45. private:  
  46.     CComPtr<IWebBrowser2>  m_spWebBrowser;  
  47.     BOOL m_fAdvised;  
  48. };  
  49. OBJECT_ENTRY_AUTO(__uuidof(HelloWorldBHO), CHelloWorldBHO)  
// HelloWorldBHO.h : CHelloWorldBHO 的声明

#pragma once
#include "resource.h"       // 主符号

#include <shlguid.h>
#include <exdispid.h>

#include "HelloWorld_i.h"



#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"
#endif

using namespace ATL;


// CHelloWorldBHO

class ATL_NO_VTABLE CHelloWorldBHO :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CHelloWorldBHO, &CLSID_HelloWorldBHO>,
	public IObjectWithSiteImpl<CHelloWorldBHO>,
	public IDispatchImpl<IHelloWorldBHO, &IID_IHelloWorldBHO, &LIBID_HelloWorldLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
	public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
{
public:
	CHelloWorldBHO()
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_HELLOWORLDBHO)

DECLARE_NOT_AGGREGATABLE(CHelloWorldBHO)

BEGIN_COM_MAP(CHelloWorldBHO)
	COM_INTERFACE_ENTRY(IHelloWorldBHO)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()



	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}
 
public:

	STDMETHOD(SetSite)(IUnknown *pUnkSite);

BEGIN_SINK_MAP(CHelloWorldBHO)
    SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()

    // DWebBrowserEvents2
    void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);

private:

    CComPtr<IWebBrowser2>  m_spWebBrowser;
	BOOL m_fAdvised;
};

OBJECT_ENTRY_AUTO(__uuidof(HelloWorldBHO), CHelloWorldBHO)
           

HelloWorldBHO.cpp:

[cpp] view plain copy print ?

  1. // HelloWorldBHO.cpp : CHelloWorldBHO 的实现  
  2. #include "stdafx.h"  
  3. #include "HelloWorldBHO.h"  
  4. // CHelloWorldBHO  
  5. STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite)  
  6. {  
  7.     if (pUnkSite != NULL)  
  8.     {  
  9.         // Cache the pointer to IWebBrowser2.  
  10.         HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);  
  11.         if (SUCCEEDED(hr))  
  12.         {  
  13.             // Register to sink events from DWebBrowserEvents2.  
  14.             hr = DispEventAdvise(m_spWebBrowser);  
  15.             if (SUCCEEDED(hr))  
  16.             {  
  17.                 m_fAdvised = TRUE;  
  18.             }  
  19.         }  
  20.     }  
  21.     else  
  22.     {  
  23.         // Unregister event sink.  
  24.         if (m_fAdvised)  
  25.         {  
  26.             DispEventUnadvise(m_spWebBrowser);  
  27.             m_fAdvised = FALSE;  
  28.         }  
  29.         // Release cached pointers and other resources here.  
  30.         m_spWebBrowser.Release();  
  31.     }  
  32.     // Call base class implementation.  
  33.     return IObjectWithSiteImpl<CHelloWorldBHO>::SetSite(pUnkSite);  
  34. }  
  35. void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)  
  36. {  
  37.     // Retrieve the top-level window from the site.  
  38.     HWND hwnd;  
  39.     HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd);  
  40.     if (SUCCEEDED(hr))  
  41.     {  
  42.         // Output a message box when page is loaded.  
  43.         MessageBox(hwnd, L"Hello World!", L"BHO", MB_OK);  
  44.     }  
  45. }  
// HelloWorldBHO.cpp : CHelloWorldBHO 的实现

#include "stdafx.h"
#include "HelloWorldBHO.h"


// CHelloWorldBHO

STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite)
{
    if (pUnkSite != NULL)
    {
        // Cache the pointer to IWebBrowser2.
        HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
        if (SUCCEEDED(hr))
        {
            // Register to sink events from DWebBrowserEvents2.
            hr = DispEventAdvise(m_spWebBrowser);
            if (SUCCEEDED(hr))
            {
                m_fAdvised = TRUE;
            }
        }
    }
    else
    {
        // Unregister event sink.
        if (m_fAdvised)
        {
            DispEventUnadvise(m_spWebBrowser);
            m_fAdvised = FALSE;
        }

        // Release cached pointers and other resources here.
        m_spWebBrowser.Release();
    }

    // Call base class implementation.
    return IObjectWithSiteImpl<CHelloWorldBHO>::SetSite(pUnkSite);
}

void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
    // Retrieve the top-level window from the site.
    HWND hwnd;
    HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd);
    if (SUCCEEDED(hr))
    {
        // Output a message box when page is loaded.
        MessageBox(hwnd, L"Hello World!", L"BHO", MB_OK);
    }
}
           

dllmain.cpp:

[cpp] view plain copy print ?

  1. // dllmain.cpp : DllMain 的实现。  
  2. #include "stdafx.h"  
  3. #include "resource.h"  
  4. #include "HelloWorld_i.h"  
  5. #include "dllmain.h"  
  6. CHelloWorldModule _AtlModule;  
  7. // DLL 入口点  
  8. extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)  
  9. {  
  10.     if (dwReason == DLL_PROCESS_ATTACH)  
  11.     {  
  12.         DisableThreadLibraryCalls(hInstance);  
  13.     }  
  14.     return _AtlModule.DllMain(dwReason, lpReserved);   
  15. }  
// dllmain.cpp : DllMain 的实现。

#include "stdafx.h"
#include "resource.h"
#include "HelloWorld_i.h"
#include "dllmain.h"

CHelloWorldModule _AtlModule;

// DLL 入口点
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hInstance);
    }
    return _AtlModule.DllMain(dwReason, lpReserved); 
}
           

HelloWorld.rgs:

[plain] view plain copy print ?

  1. HKLM {  
  2.   NoRemove SOFTWARE {  
  3.     NoRemove Microsoft {     
  4.       NoRemove Windows {  
  5.         NoRemove CurrentVersion {  
  6.           NoRemove Explorer {  
  7.             NoRemove 'Browser Helper Objects' {  
  8.               ForceRemove '{22024CC8-9043-49C7-AC80-A803A2912BF6}' = s 'HelloWorldBHO' {  
  9.                 val 'NoExplorer' = d '1'  
  10.               }  
  11.             }  
  12.           }  
  13.         }  
  14.       }  
  15.     }  
  16.   }  
  17. }  
HKLM {
  NoRemove SOFTWARE {
    NoRemove Microsoft {   
      NoRemove Windows {
        NoRemove CurrentVersion {
          NoRemove Explorer {
            NoRemove 'Browser Helper Objects' {
              ForceRemove '{22024CC8-9043-49C7-AC80-A803A2912BF6}' = s 'HelloWorldBHO' {
                val 'NoExplorer' = d '1'
              }
            }
          }
        }
      }
    }
  }
}
           

目前要修改的也就那么几个文件,然后关闭安全软件,进行build,生成的dll会自动注册到注册表里去,如图:

before:

C++开发BHO之HelloWorld原文:

after:

C++开发BHO之HelloWorld原文:

然后打开IE,如图:

C++开发BHO之HelloWorld原文:

也可以在IE的管理加载项中看到,工具-管理加载项:

C++开发BHO之HelloWorld原文:

可以启用或者禁用BHO。

这样,就完成了HelloWorld版本的BHO的开发。