打造个性化的internet explorer
来源:百度文库 编辑:神马文学网 时间:2024/04/25 02:20:53
打造个性化的Internet Explorer
作者:孙辉
在Microsoft的软件哲学中,框架窗口是一个十分重要的角色,这类窗口简直无处不在。所谓框架窗口,就是四个窗口边上具有停靠对象能力的窗口对象,从现象上看,框架窗口有十分特别的“边”,Microsoft构造的许许多多的东西都可以在其边上“靠泊”,这就是所谓的“Docking”,Internet Explorer是Microsoft的一个典型的运用框架窗口的代表作品。今天的IE,在不知不觉中,你会发现工具栏中会多出一些东西来,这一切的缘由归根到底都是“边”在作祟,本文试图抛砖引玉,将你带入丰富多彩的IE扩展世界。
Band,IE扩展的利器
Band,是Windows Shell对象,当Microsoft将Internet Explorer与Windows Shell彻底集成时,Band对象就成为Windows Shell的一个活跃对象,典型的Band对象有IE的搜索栏、收藏栏、历史栏以及IE的各种工具栏等等。Microsoft公开的Band对象有四类,一类是桌面Band,如位于任务栏上的“快速启动”、“Windows Media Player”等工具条。而其他三种Band,则均出现在IE之中,包括工具栏Band(如MSN Search工具栏)、Explorer Band(如历史、媒体等出现在IE左侧的窗口)和通讯Band(如位于用户区下方的“讨论”窗口)。
Band对象停靠在对应于IE的框架窗口的四周,因此,给IE的界面提供了灵活的扩张机制。由于IE的用户区基本上用于HTML对象的浏览,因此现在流行的B/S结构不能充分地运用IE灵活、强大的扩展机制,一旦可以将具有C/S结构特征的自定义子窗口挂接到IE的四周,将可以将IE打造成同时具备B/S、C/S体系优势的开发框架。现在,Microsoft已经在Office系列产品中体现类似的思路,例如在Microsoft Word以及Excel中,Microsoft引进了Actions Pane对象,使得位于中心的Office文档可以与停靠在一边的Actions Pane对象进行通讯、交互操作等等,如图1所示。
图1 Word右侧的“任务窗格”对象是个典型的Docking对象,这里体现了Microsoft最新的Smart Document技术
开发你的Band对象,让IE因你而变
从IE4开始,Band对象就已经存在了,但其复杂的接口使大多数开发人员望而却步。一个典型的Band对象是一个COM对象,需要实现如下几个接口:
IDeskBand IObjectWithSite IPersistStream IInputObject
每个接口各自包含一些列方法。接口IDeskBand决定了Band对象的基本行为,接口IObjectWithSite提供了Band对象与IE的通讯渠道,接口IInputObject提供了Band对象的输入消息处理,特别该接口是处理对话框消息的关键所在,当需要实现桌面Band对象时,接口IPersistStream提供实现相关的信息存储(如Band对象的位置)。关于Band对象的一般介绍,可以参考Microsoft Internet SDK技术文档,由于Microsoft仅提供了很少的文档与范例,因此Band对象基本上被广大开发者忽略了。事实上,IE内部的扩展性十分强大(当然,强大也意味着危险),就其扩展编程接口而言,IE的扩展性并不输给FireFox。
理论上,只要支持COM技术的开发工具,都可以用来构造Band对象,然而对于更深层的COM技术细节而言,ATL/MFC类库还是最佳的选择。毋庸置疑,MFC具备强大的界面构造能力,然而,由于缺乏一个有效的衔接,MFC类库与深层COM技术开发一直被一层很薄的“纸”隔开了,这一点不能不说是个遗憾。
CTangramBandImpl,一个Band对象的起点
首先,我们需要一个构造Band对象的起点,为此我们构造一个基类,以实现上面提到的四个接口,CTangramBandImpl对象的详细实现细节请参考我们提供的源代码,以下是其基本构造:
class CTangramBandImpl :
public IDeskBand,
public IObjectWithSite,
public IPersistStream,
public IInputObject
{
public:
CTangramBandImpl(void);
virtual ~CTangramBandImpl(void);
// IDeskBand
public:
STDMETHOD(GetBandInfo)(DWORD dwBandID, DWORD dwViewMode,
DESKBANDINFO* pdbi);
// IObjectWithSite
public:
STDMETHOD(SetSite)(IUnknown* pUnkSite);
STDMETHOD(GetSite)(REFIID riid, void **ppvSite);
// IOleWindow
public:
STDMETHOD(GetWindow)(HWND* phwnd);
STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);
// IDockingWindow
public:
STDMETHOD(CloseDW)(unsigned long dwReserved);
STDMETHOD(ResizeBorderDW)(const RECT* prcBorder,
IUnknown* punkToolbarSite, BOOL fReserved);
STDMETHOD(ShowDW)(BOOL fShow);
// IPersist
public:
STDMETHOD(GetClassID)(CLSID *pClassID);
// IPersistStream
public:
STDMETHOD(IsDirty)(void);
STDMETHOD(Load)(IStream *pStm);
STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);
STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize);
// IInputObject
public:
STDMETHOD(HasFocusIO)(void);
STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg);
STDMETHOD(UIActivateIO)(BOOL fActivate, LPMSG lpMsg);
public:
BOOL m_bFocus;
BOOL m_bCommBand;
void FocusChange(BOOL);
protected:
virtual BOOL RegisterAndCreateWindow(){return false;};
virtual void SetBandTitle(DESKBANDINFO* pdbi){};
CFrameWnd* m_pFrameWnd;
DWORD m_dwBandID;
DWORD m_dwViewMode;
BOOL m_bShow;
BOOL m_bEnterHelpMode;
HWND m_hWndParent;
IInputObjectSite* m_pSite;
};
对于IE,除了工具栏外,我们将停靠于IE框架左侧的Band称为Explorer Band,而将停靠于框架底边的Band称为通讯Band(Communication Band),从COM的角度看,这两类对象分别属于不同的对象范畴(Category),所有这两类对象均被罗列在IE的View菜单的“Explorer Bar”子菜单中。我们实现的Explorer Band对象的类结构如下:
class ATL_NO_VTABLE CBand : public CTangramBandImpl,
public CComObjectRootEx,
public CComCoClass,
public IDispatchImpl
{
public:
CBand();
DECLARE_REGISTRY_RESOURCEID(IDR_BAND)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_CATEGORY_MAP(CBand)
IMPLEMENTED_CATEGORY(CATID_InfoBand)
IMPLEMENTED_CATEGORY(CATID_DeskBand)
END_CATEGORY_MAP()
BEGIN_COM_MAP(CBand)
COM_INTERFACE_ENTRY(IBand)
COM_INTERFACE_ENTRY(IOleWindow)
COM_INTERFACE_ENTRY(IObjectWithSite)
COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
COM_INTERFACE_ENTRY(IPersist)
COM_INTERFACE_ENTRY(IPersistStream)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
protected:
virtual BOOL RegisterAndCreateWindow();
virtual void SetBandTitle(DESKBANDINFO* pdbi);
};
代码片断:
BEGIN_CATEGORY_MAP(CBand)
IMPLEMENTED_CATEGORY(CATID_InfoBand)
IMPLEMENTED_CATEGORY(CATID_DeskBand)
END_CATEGORY_MAP()
表明CBand对象隶属两个对象范畴,分别是桌面Band以及Explorer Band,因此,此类对象可以停靠于Windows Shell的桌面,同时也可以停靠于IE框架窗口的左侧,当你在桌面的工具栏中点击鼠标右键,选择Toolbars时,你会看到创建桌面TangramBand的菜单项:
Communication Band对象CHBand的类结构与CBand的基本一致,最大的区别是:
BEGIN_CATEGORY_MAP(CHBand)
IMPLEMENTED_CATEGORY(CATID_CommBand)
END_CATEGORY_MAP()
由于Band对象实现了接口IObjectWithSite,因此,Band对象可以通过该接口得到Band对象所从属的IE实例。为此,我们注意到CTangramBandImpl中已经实现了IObjectWithSite的方法SetSite,我们可以在其中添加如下代码:
IOleCommandTarget* pCmdTarget = NULL;
IWebBrowser2* m_pBrowser;
HRESULT hr = pUnkSite->QueryInterface(IID_IOleCommandTarget,
(LPVOID*)&pCmdTarget);
if(SUCCEEDED(hr))
{
IServiceProvider* pSP;
hr = pCmdTarget->QueryInterface(IID_IServiceProvider,
(LPVOID*)&pSP);
pCmdTarget->Release();
if (SUCCEEDED(hr))
{
hr = pSP->QueryService(SID_SWebBrowserApp,
IID_IWebBrowser2, (LPVOID*)&m_pBrowser);
if(hr==S_OK)
TRACE(_T("Get m_pBrowser: %x\n"),m_pBrowser);
pSP->Release();
}
}
这样就可以以得到这个Band对象对应的IE实例(即上述代码中的m_pBrowser)。通过m_pBrowser,Band对象可以访问当前浏览器浏览的页面、调用网页中的脚本代码以及实现其他的Band对象与网页之间的交互功能。
实现基于MFC的Band对象
为了将MFC类库的强大功能自然纳入Band对象,我们需要一个基于MFC的Frame窗口。我们注意到,CTangramBandImpl已经包含了一个成员变量:
CFrameWnd* m_pFrameWnd;
这个变量建立了一座衔接Band对象与MFC类库的桥梁,在每个Band对象的RegisterAndCreateWindow函数中,均包含如下代码:
BOOL CHBand::RegisterAndCreateWindow()
{
RECT rect;
::GetClientRect(m_hWndParent, &rect);
AFX_MANAGE_STATE(AfxGetStaticModuleState());
theApp.m_pBand = this;
m_pFrameWnd = new CTangramBandFrame();
CCreateContext m_Context;
m_Context.m_pNewViewClass = RUNTIME_CLASS(TestFormView);
CWnd* pWnd = CWnd::FromHandle(m_hWndParent);
m_pFrameWnd->Create(NULL,_T("TangramBand"),
WS_CHILD, CRect(rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top),
pWnd, NULL, NULL, &m_Context);
theApp.m_pBand = NULL;
return true;
}
我们注意到,这段代码创建了一个MFC CFrameWnd对象m_pFrameWnd。由此,一切关于MFC的代码技巧自然而然地盘活了,我们看到一个典型的MFC框架被融入IE之中:
BOOL CTangramBandFrame::OnCreateClient(LPCREATESTRUCT lpcs,
CCreateContext* pContext)
{
if(!m_pBand->m_bCommBand)
{
m_SplitterWnd.CreateStatic(this, 2, 1);
m_SplitterWnd.CreateView(0, 0, RUNTIME_CLASS(TestFormView),
CSize(0, 100), NULL);
m_SplitterWnd.CreateView(1, 0, RUNTIME_CLASS(TestFormView2),
CSize(0, 100), NULL);
}
else
{
m_SplitterWnd.CreateStatic(this, 1, 2);
m_SplitterWnd.CreateView(0, 0, RUNTIME_CLASS(TestFormView),
CSize(150, 100), NULL);
m_SplitterWnd.CreateView(0, 1, RUNTIME_CLASS(TestFormView2),
CSize(0, 0), NULL);
}
return true;
}
由于Band对象存在于一个动态链接库中,故创建MFC对象时要注意在合适的位置调用代码:
AFX_MANAGE_STATE(AfxGetStaticModuleState());
以使得MFC能够正确处理消息。
输入消息处理
接口IInputObject用于管理Band对象的输入以及对话框、加速键消息,关于MFC消息,由于Band对象本质上是一种IE插件,故消息队列由IE控制,因此MFC窗口的消息处理是个关键问题。当Band对象捕获输入焦点时,我们必须保证MFC窗口消息被正确处理,下述代码:
STDMETHODIMP CTangramBandImpl::TranslateAcceleratorIO(LPMSG lpMsg)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if(m_bFocus&&theApp.m_pWnd)
{
theApp.m_pWnd->PreTranslateMessage(lpMsg);
TRACE(_T("TranslateAcceleratorIO\n"));
return S_OK;
}
return S_FALSE;
}
用来处理当前具有输入焦点的MFC窗口theApp.m_pWnd的相关消息,因此具有输入焦点的MFC窗口必须重载函数PreTranslateMessage,特别是CFormView的派生对象,在范例代码中我们给出了重载该函数的例子。
调试与中文处理
Band对象的调试例程是IE,因此需要修改工程配置,使得调试过程定向到IE。为使得Band对象能够正确接受中文输入,代码工程必须是基于UNICODE的。
您可以到杂志的站点(http://mag.csdn.net/msdn)上下载本刊附带的源代码,其中的MsdnJxControl解决方案中有本文所提到的项目的完整实现。该解决方案已经为您做好了所有的配置工作,但还是希望您能够通过属性面板仔细观察该解决方案的具体设置。
小结
正如Microsoft系列的其他产品一样,Internet Explorer中存在着丰富的扩展空间。对于Microsoft而言,框架窗口的四周存在着可停靠对象的口岸,因此你可以在这些岸边开拓你的软件空间以展示你的软件魅力,如果你读到了本文,那么你就开始吧,充满诱惑的海岸,等待你去开拓。
_xyz
作者:孙辉
在Microsoft的软件哲学中,框架窗口是一个十分重要的角色,这类窗口简直无处不在。所谓框架窗口,就是四个窗口边上具有停靠对象能力的窗口对象,从现象上看,框架窗口有十分特别的“边”,Microsoft构造的许许多多的东西都可以在其边上“靠泊”,这就是所谓的“Docking”,Internet Explorer是Microsoft的一个典型的运用框架窗口的代表作品。今天的IE,在不知不觉中,你会发现工具栏中会多出一些东西来,这一切的缘由归根到底都是“边”在作祟,本文试图抛砖引玉,将你带入丰富多彩的IE扩展世界。
Band,IE扩展的利器
Band,是Windows Shell对象,当Microsoft将Internet Explorer与Windows Shell彻底集成时,Band对象就成为Windows Shell的一个活跃对象,典型的Band对象有IE的搜索栏、收藏栏、历史栏以及IE的各种工具栏等等。Microsoft公开的Band对象有四类,一类是桌面Band,如位于任务栏上的“快速启动”、“Windows Media Player”等工具条。而其他三种Band,则均出现在IE之中,包括工具栏Band(如MSN Search工具栏)、Explorer Band(如历史、媒体等出现在IE左侧的窗口)和通讯Band(如位于用户区下方的“讨论”窗口)。
Band对象停靠在对应于IE的框架窗口的四周,因此,给IE的界面提供了灵活的扩张机制。由于IE的用户区基本上用于HTML对象的浏览,因此现在流行的B/S结构不能充分地运用IE灵活、强大的扩展机制,一旦可以将具有C/S结构特征的自定义子窗口挂接到IE的四周,将可以将IE打造成同时具备B/S、C/S体系优势的开发框架。现在,Microsoft已经在Office系列产品中体现类似的思路,例如在Microsoft Word以及Excel中,Microsoft引进了Actions Pane对象,使得位于中心的Office文档可以与停靠在一边的Actions Pane对象进行通讯、交互操作等等,如图1所示。
图1 Word右侧的“任务窗格”对象是个典型的Docking对象,这里体现了Microsoft最新的Smart Document技术
开发你的Band对象,让IE因你而变
从IE4开始,Band对象就已经存在了,但其复杂的接口使大多数开发人员望而却步。一个典型的Band对象是一个COM对象,需要实现如下几个接口:
IDeskBand IObjectWithSite IPersistStream IInputObject
每个接口各自包含一些列方法。接口IDeskBand决定了Band对象的基本行为,接口IObjectWithSite提供了Band对象与IE的通讯渠道,接口IInputObject提供了Band对象的输入消息处理,特别该接口是处理对话框消息的关键所在,当需要实现桌面Band对象时,接口IPersistStream提供实现相关的信息存储(如Band对象的位置)。关于Band对象的一般介绍,可以参考Microsoft Internet SDK技术文档,由于Microsoft仅提供了很少的文档与范例,因此Band对象基本上被广大开发者忽略了。事实上,IE内部的扩展性十分强大(当然,强大也意味着危险),就其扩展编程接口而言,IE的扩展性并不输给FireFox。
理论上,只要支持COM技术的开发工具,都可以用来构造Band对象,然而对于更深层的COM技术细节而言,ATL/MFC类库还是最佳的选择。毋庸置疑,MFC具备强大的界面构造能力,然而,由于缺乏一个有效的衔接,MFC类库与深层COM技术开发一直被一层很薄的“纸”隔开了,这一点不能不说是个遗憾。
CTangramBandImpl,一个Band对象的起点
首先,我们需要一个构造Band对象的起点,为此我们构造一个基类,以实现上面提到的四个接口,CTangramBandImpl对象的详细实现细节请参考我们提供的源代码,以下是其基本构造:
class CTangramBandImpl :
public IDeskBand,
public IObjectWithSite,
public IPersistStream,
public IInputObject
{
public:
CTangramBandImpl(void);
virtual ~CTangramBandImpl(void);
// IDeskBand
public:
STDMETHOD(GetBandInfo)(DWORD dwBandID, DWORD dwViewMode,
DESKBANDINFO* pdbi);
// IObjectWithSite
public:
STDMETHOD(SetSite)(IUnknown* pUnkSite);
STDMETHOD(GetSite)(REFIID riid, void **ppvSite);
// IOleWindow
public:
STDMETHOD(GetWindow)(HWND* phwnd);
STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);
// IDockingWindow
public:
STDMETHOD(CloseDW)(unsigned long dwReserved);
STDMETHOD(ResizeBorderDW)(const RECT* prcBorder,
IUnknown* punkToolbarSite, BOOL fReserved);
STDMETHOD(ShowDW)(BOOL fShow);
// IPersist
public:
STDMETHOD(GetClassID)(CLSID *pClassID);
// IPersistStream
public:
STDMETHOD(IsDirty)(void);
STDMETHOD(Load)(IStream *pStm);
STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);
STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize);
// IInputObject
public:
STDMETHOD(HasFocusIO)(void);
STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg);
STDMETHOD(UIActivateIO)(BOOL fActivate, LPMSG lpMsg);
public:
BOOL m_bFocus;
BOOL m_bCommBand;
void FocusChange(BOOL);
protected:
virtual BOOL RegisterAndCreateWindow(){return false;};
virtual void SetBandTitle(DESKBANDINFO* pdbi){};
CFrameWnd* m_pFrameWnd;
DWORD m_dwBandID;
DWORD m_dwViewMode;
BOOL m_bShow;
BOOL m_bEnterHelpMode;
HWND m_hWndParent;
IInputObjectSite* m_pSite;
};
对于IE,除了工具栏外,我们将停靠于IE框架左侧的Band称为Explorer Band,而将停靠于框架底边的Band称为通讯Band(Communication Band),从COM的角度看,这两类对象分别属于不同的对象范畴(Category),所有这两类对象均被罗列在IE的View菜单的“Explorer Bar”子菜单中。我们实现的Explorer Band对象的类结构如下:
class ATL_NO_VTABLE CBand : public CTangramBandImpl,
public CComObjectRootEx
public CComCoClass
public IDispatchImpl
{
public:
CBand();
DECLARE_REGISTRY_RESOURCEID(IDR_BAND)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_CATEGORY_MAP(CBand)
IMPLEMENTED_CATEGORY(CATID_InfoBand)
IMPLEMENTED_CATEGORY(CATID_DeskBand)
END_CATEGORY_MAP()
BEGIN_COM_MAP(CBand)
COM_INTERFACE_ENTRY(IBand)
COM_INTERFACE_ENTRY(IOleWindow)
COM_INTERFACE_ENTRY(IObjectWithSite)
COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
COM_INTERFACE_ENTRY(IPersist)
COM_INTERFACE_ENTRY(IPersistStream)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
protected:
virtual BOOL RegisterAndCreateWindow();
virtual void SetBandTitle(DESKBANDINFO* pdbi);
};
代码片断:
BEGIN_CATEGORY_MAP(CBand)
IMPLEMENTED_CATEGORY(CATID_InfoBand)
IMPLEMENTED_CATEGORY(CATID_DeskBand)
END_CATEGORY_MAP()
表明CBand对象隶属两个对象范畴,分别是桌面Band以及Explorer Band,因此,此类对象可以停靠于Windows Shell的桌面,同时也可以停靠于IE框架窗口的左侧,当你在桌面的工具栏中点击鼠标右键,选择Toolbars时,你会看到创建桌面TangramBand的菜单项:
Communication Band对象CHBand的类结构与CBand的基本一致,最大的区别是:
BEGIN_CATEGORY_MAP(CHBand)
IMPLEMENTED_CATEGORY(CATID_CommBand)
END_CATEGORY_MAP()
由于Band对象实现了接口IObjectWithSite,因此,Band对象可以通过该接口得到Band对象所从属的IE实例。为此,我们注意到CTangramBandImpl中已经实现了IObjectWithSite的方法SetSite,我们可以在其中添加如下代码:
IOleCommandTarget* pCmdTarget = NULL;
IWebBrowser2* m_pBrowser;
HRESULT hr = pUnkSite->QueryInterface(IID_IOleCommandTarget,
(LPVOID*)&pCmdTarget);
if(SUCCEEDED(hr))
{
IServiceProvider* pSP;
hr = pCmdTarget->QueryInterface(IID_IServiceProvider,
(LPVOID*)&pSP);
pCmdTarget->Release();
if (SUCCEEDED(hr))
{
hr = pSP->QueryService(SID_SWebBrowserApp,
IID_IWebBrowser2, (LPVOID*)&m_pBrowser);
if(hr==S_OK)
TRACE(_T("Get m_pBrowser: %x\n"),m_pBrowser);
pSP->Release();
}
}
这样就可以以得到这个Band对象对应的IE实例(即上述代码中的m_pBrowser)。通过m_pBrowser,Band对象可以访问当前浏览器浏览的页面、调用网页中的脚本代码以及实现其他的Band对象与网页之间的交互功能。
实现基于MFC的Band对象
为了将MFC类库的强大功能自然纳入Band对象,我们需要一个基于MFC的Frame窗口。我们注意到,CTangramBandImpl已经包含了一个成员变量:
CFrameWnd* m_pFrameWnd;
这个变量建立了一座衔接Band对象与MFC类库的桥梁,在每个Band对象的RegisterAndCreateWindow函数中,均包含如下代码:
BOOL CHBand::RegisterAndCreateWindow()
{
RECT rect;
::GetClientRect(m_hWndParent, &rect);
AFX_MANAGE_STATE(AfxGetStaticModuleState());
theApp.m_pBand = this;
m_pFrameWnd = new CTangramBandFrame();
CCreateContext m_Context;
m_Context.m_pNewViewClass = RUNTIME_CLASS(TestFormView);
CWnd* pWnd = CWnd::FromHandle(m_hWndParent);
m_pFrameWnd->Create(NULL,_T("TangramBand"),
WS_CHILD, CRect(rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top),
pWnd, NULL, NULL, &m_Context);
theApp.m_pBand = NULL;
return true;
}
我们注意到,这段代码创建了一个MFC CFrameWnd对象m_pFrameWnd。由此,一切关于MFC的代码技巧自然而然地盘活了,我们看到一个典型的MFC框架被融入IE之中:
BOOL CTangramBandFrame::OnCreateClient(LPCREATESTRUCT lpcs,
CCreateContext* pContext)
{
if(!m_pBand->m_bCommBand)
{
m_SplitterWnd.CreateStatic(this, 2, 1);
m_SplitterWnd.CreateView(0, 0, RUNTIME_CLASS(TestFormView),
CSize(0, 100), NULL);
m_SplitterWnd.CreateView(1, 0, RUNTIME_CLASS(TestFormView2),
CSize(0, 100), NULL);
}
else
{
m_SplitterWnd.CreateStatic(this, 1, 2);
m_SplitterWnd.CreateView(0, 0, RUNTIME_CLASS(TestFormView),
CSize(150, 100), NULL);
m_SplitterWnd.CreateView(0, 1, RUNTIME_CLASS(TestFormView2),
CSize(0, 0), NULL);
}
return true;
}
由于Band对象存在于一个动态链接库中,故创建MFC对象时要注意在合适的位置调用代码:
AFX_MANAGE_STATE(AfxGetStaticModuleState());
以使得MFC能够正确处理消息。
输入消息处理
接口IInputObject用于管理Band对象的输入以及对话框、加速键消息,关于MFC消息,由于Band对象本质上是一种IE插件,故消息队列由IE控制,因此MFC窗口的消息处理是个关键问题。当Band对象捕获输入焦点时,我们必须保证MFC窗口消息被正确处理,下述代码:
STDMETHODIMP CTangramBandImpl::TranslateAcceleratorIO(LPMSG lpMsg)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if(m_bFocus&&theApp.m_pWnd)
{
theApp.m_pWnd->PreTranslateMessage(lpMsg);
TRACE(_T("TranslateAcceleratorIO\n"));
return S_OK;
}
return S_FALSE;
}
用来处理当前具有输入焦点的MFC窗口theApp.m_pWnd的相关消息,因此具有输入焦点的MFC窗口必须重载函数PreTranslateMessage,特别是CFormView的派生对象,在范例代码中我们给出了重载该函数的例子。
调试与中文处理
Band对象的调试例程是IE,因此需要修改工程配置,使得调试过程定向到IE。为使得Band对象能够正确接受中文输入,代码工程必须是基于UNICODE的。
您可以到杂志的站点(http://mag.csdn.net/msdn)上下载本刊附带的源代码,其中的MsdnJxControl解决方案中有本文所提到的项目的完整实现。该解决方案已经为您做好了所有的配置工作,但还是希望您能够通过属性面板仔细观察该解决方案的具体设置。
小结
正如Microsoft系列的其他产品一样,Internet Explorer中存在着丰富的扩展空间。对于Microsoft而言,框架窗口的四周存在着可停靠对象的口岸,因此你可以在这些岸边开拓你的软件空间以展示你的软件魅力,如果你读到了本文,那么你就开始吧,充满诱惑的海岸,等待你去开拓。
_xyz
打造个性化的internet explorer
如何修改 Internet Explorer 的主页设置?
如何修改 Internet Explorer 的主页设置?
Internet Explorer的Logo演变史
Internet Explorer 下载
Internet Explorer是什么东西?
如何使用BHO定制你的Internet Explorer浏览器,good
IE9(Internet Explorer 9.0)的菜单栏怎样显示?
打造个性化的IE按钮
Internet Explorer Toolbar (Deskband) Tutorial
Internet Explorer Toolbar (Deskband) Tutorial...
Internet Explorer Toolbar (Deskband) Tutorial...
Internet Explorer and Connection Limits
Internet Explorer 8 使用技巧
Internet Explorer 8 使用技巧
Internet Explorer 8:隐私策略
打造个性化生活的SOHO创业
[Python模块]PAMIE -- Python Automated Module For Internet Explorer - limodou的学习记录 - DonewsBlog
如何使用BHO定制你的Internet Explorer浏览器 - IE编程 - vc++...
“Internet Explorer 已经遇到加载项故障并且需要关闭”的故障解决方案 - ...
2.Internet?Explorer无法显示页面的问题 -搜房问答
Internet Explorer遇到问题需要关闭如何解决? - ★秋水伊人★的日志 - ...
我的IE经常出现\Microsoft Internet Explorer遇到问题需要关闭....
Migrate apps from Internet Explorer to Mozilla