(转)C++开发BHO(以HelloWorld对话框为例子)
2014-07-13 16:26
369 查看
原文:
http://msdn.microsoft.com/en-us/library/bb250489(v=vs.85).aspx
开发工具VS2010。
步骤如图:
生成的HelloWorldBHO.h的代码如下:
[cpp]
view plaincopyprint?
// 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 plaincopyprint?
// HelloWorldBHO.cpp : CHelloWorldBHO 的实现
#include "stdafx.h"
#include "HelloWorldBHO.h"
// CHelloWorldBHO
HelloWorld.cpp的代码如下:
[cpp]
view plaincopyprint?
// 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 plaincopyprint?
// 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 plaincopyprint?
HKCR
{
}
HelloWorldBHO.rgs的内容如下:
[plain]
view plaincopyprint?
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 plaincopyprint?
// 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 plaincopyprint?
#include <shlguid.h>
#include <exdispid.h>
2、增加一个公有的SetSite方法:
[cpp]
view plaincopyprint?
public:
STDMETHOD(SetSite)(IUnknown *pUnkSite);
3、增加私有的成员变量:
[cpp]
view plaincopyprint?
private:
CComPtr<IWebBrowser2> m_spWebBrowser;
BOOL m_fAdvised;
4、多继承一个类:
[cpp]
view plaincopyprint?
public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
5、增加公有的方法OnDocumentComplete:
[cpp]
view plaincopyprint?
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 plaincopyprint?
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 plaincopyprint?
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 plaincopyprint?
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 plaincopyprint?
// 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 plaincopyprint?
// 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 plaincopyprint?
// 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 plaincopyprint?
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:
after:
然后打开IE,如图:
也可以在IE的管理加载项中看到,工具-管理加载项:
可以启用或者禁用BHO。
这样,就完成了HelloWorld版本的BHO的开发。
http://msdn.microsoft.com/en-us/library/bb250489(v=vs.85).aspx
开发工具VS2010。
步骤如图:
生成的HelloWorldBHO.h的代码如下:
[cpp]
view plaincopyprint?
// 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.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 plaincopyprint?
// HelloWorldBHO.cpp : CHelloWorldBHO 的实现
#include "stdafx.h"
#include "HelloWorldBHO.h"
// CHelloWorldBHO
// HelloWorldBHO.cpp : CHelloWorldBHO 的实现 #include "stdafx.h" #include "HelloWorldBHO.h" // CHelloWorldBHO
HelloWorld.cpp的代码如下:
[cpp]
view plaincopyprint?
// 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;
}
// 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 plaincopyprint?
// 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);
}
// 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 plaincopyprint?
HKCR
{
}
HKCR { }
HelloWorldBHO.rgs的内容如下:
[plain]
view plaincopyprint?
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'
}
}
}
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 plaincopyprint?
// 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 : 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 plaincopyprint?
#include <shlguid.h>
#include <exdispid.h>
#include <shlguid.h> #include <exdispid.h>
2、增加一个公有的SetSite方法:
[cpp]
view plaincopyprint?
public:
STDMETHOD(SetSite)(IUnknown *pUnkSite);
public: STDMETHOD(SetSite)(IUnknown *pUnkSite);
3、增加私有的成员变量:
[cpp]
view plaincopyprint?
private:
CComPtr<IWebBrowser2> m_spWebBrowser;
BOOL m_fAdvised;
private: CComPtr<IWebBrowser2> m_spWebBrowser; BOOL m_fAdvised;
4、多继承一个类:
[cpp]
view plaincopyprint?
public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
5、增加公有的方法OnDocumentComplete:
[cpp]
view plaincopyprint?
BEGIN_SINK_MAP(CHelloWorldBHO)
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()
// DWebBrowserEvents2
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 plaincopyprint?
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);
}
}
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 plaincopyprint?
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance,
DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hInstance);
}
return _AtlModule.DllMain(dwReason, lpReserved);
}
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 plaincopyprint?
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'
}
}
}
}
}
}
}
}
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 plaincopyprint?
// 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.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 plaincopyprint?
// 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);
}
}
// 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 plaincopyprint?
// 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);
}
// 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 plaincopyprint?
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'
}
}
}
}
}
}
}
}
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:
after:
然后打开IE,如图:
也可以在IE的管理加载项中看到,工具-管理加载项:
可以启用或者禁用BHO。
这样,就完成了HelloWorld版本的BHO的开发。
相关文章推荐
- C++开发BHO之HelloWorld
- C++开发BHO之HelloWorld
- 小例子学J2ME手机游戏开发--(一)初具手机游戏框架的HelloWorld
- Android-NDK开发之第四个例子--用C/C++调用Java
- hadoop上C++开发两种方式的例子
- 一个简单的Eclipse插件开发的例子——HelloWorld【转载】
- Chromium开发--入门C++小例子
- 用eclipse开发BPELd的HelloWorld例子
- 安卓开发04:对话框例子
- NVIDIA Jetson TK1学习与开发(五):helloworld的C版本与C++版本
- 使用carbide.c++搭建s60开发环境(跑出helloworld)(转载)
- Redis 的 C++开发包 使用例子
- C/C++开发语言系列之21---C++函数指针的2个例子
- hadoop上C++开发两种方式的例子
- [Leap Motion开发系列]理解C++应用例子
- MTK开发中学习资源分配,菜单,字符串,对话框的综合例子
- Android-NDK开发之第四个例子--用C/C++调用Java
- 安卓开发04:对话框例子
- 使用C++编写的一个Find(查找)对话框例子
- Redis 的 C++开发包 使用例子