青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

旅途

如果想飛得高,就該把地平線忘掉

Internet Explorer 編程簡述(八)實現瀏覽歷史菜單

關鍵字:ITravelLogStg, IEnumTravelLogEntry, ITravelLogEntry

 

1、概述

Internet Explorer的瀏覽歷史菜單在4.0版本開始出現,但直到5.5之前,微軟都未公布用于訪問瀏覽歷史的COM接口,如今已是IE6.0大行其道的年代,用于訪問瀏覽歷史的接口也早已公布多時,本文的目的則是試圖拋磚引玉,簡單介紹用于訪問瀏覽歷史的Travel Log接口,并用一個小小的類CIETravelLog來實現對Travel Log的封裝。

 

2、IOmHistory接口

在早些時候的MSDN中,我們能夠查閱到關于瀏覽歷史的接口僅有IOmHistory,而該接口實際上對應的是瀏覽器中可以通過腳本訪問的“history”對象。對于“history”對象,MSDN中是這樣說的:

 

For security reasons, the history object does not expose the actual URLs in the browser history. It does allow navigation through the browser history by exposing the back, forward, and go methods. A particular document in the browser history can be identified as an index relative to the current page. For example, specifying -1 as a parameter for the go method is the equivalent of clicking the Back button.

 

This object is available in script as of Microsoft Internet Explorer 3.0.

 

即為了安全的原因,IOmHistory接口僅提供了有限的幾個方法來完成在瀏覽器中前進、后退等操作,并沒有提供訪問歷史列表Url的能力。這也難怪,該接口在IE 3.0時代已經存在,而當時IE并不成熟,可編程能力也不甚強大。一直到IE 4.0通過與Windows 98捆綁銷售一統天下之后,相關的文檔才逐漸豐富,多窗口瀏覽器等基于Internet Explorer/WebBrowser Control的應用軟件也才鋪天蓋地開來。但在IE 5.5接口公布之前,要完全模擬IE的Travel Log行為,并不是一件容易的事。最容易想到的方法就是在BeforeNavigate、DocumentComplete等事件發生之時記錄/修改Url并加以保存(我在早些時候也這樣做過),但是效果不甚理想,尤其是瀏覽包含Frame的網頁時,處理更是麻煩。當然,要完全模擬亦非難事,只不過開發人員都知道微軟公布接口是早晚的事,所以也沒有人花大力氣在模擬IE的Travel Log行為上。

 

3、Travel Log簡介

Internet Explorer 5.5推出以后,Travel Log接口也就開始出現在MSDN中,它是專門為OLE嵌入WebBrowser Control的應用程序設計的,其目的是“提高和加強用戶的訪問日志體驗”(improve and enhance the user's travel log experience)。事實上,稍后我會提到,Travel Log接口正日益成為應用程序中的重要接口之一。

微軟公布的Travel Log共包含三個接口:ITravelLogStg, IEnumTravelLogEntry和ITravelLogEntry。

 

  • ITravelLogStg——該接口提供了用于在Travel Log中添加、刪除、枚舉日志(瀏覽歷史)的方法,本文需要用到的幾個方法列舉如下:

方法名     用途

EnumEntries 為訪問日志項創建枚舉器(IEnumTravelLogEntry接口指針)

GetRelativeEntry 返回一個日志項

TravelTo 訪問一個日志項

  • IEnumTravelLogEntry——該接口提供用于枚舉日志項所必需的方法,本文只用到一個方法:

方法名     用途

Next   枚舉下一個日志項(返回ITravelLogEntry接口指針)

  • ITravelLogEntry——該接口只有兩個方法,分別用于返回日志項的Title和Url:

方法名     用途

GetTitle 返回日志項的Title

GetURL 返回日志項的Url

 

接口準備好了,我們也就很容易得知它們之間的關系:

  • 要得到相對于當前頁面的日志項列表,首先應通過ITravelLogStg接口創建一個枚舉器(IEnumTravelLogEntry接口)。
  • 通過IEnumTravelLogEntry枚舉器的Next方法枚舉出一個個的日志項(ITravelLogEntry接口)。
  • 由ITravelLogEntry接口獲取日志項所代表的網頁的Title和Url并加以處理。
  • 訪問相對于當前頁面的某個日志項時,首先由ITravelLogStg的GetRelativeEntry方法根據與當前頁的距離得到ITravelLogEntry接口,再將后者傳入ITravelLogStg的TravelTo方法以達到訪問日志項的目的(如前進和后退)。

 

也許不是太恰當,我對UML也不熟悉,借用一個偽UML序列圖表示其關系如下:

 

 

 Travel log

 

4、封裝Travel Log

接下來,我們就用一個簡單的類來完成對Travel Log的封裝。如下所示,tlogstg.h包含了Travel Log的相關接口聲明,該頭文件可以在Platform SDK中找到。

 

#include "tlogstg.h"

 

class CIETravelLog

{

private:

ITravelLogStg *m_pTravelLogStg;

IEnumTravelLogEntry *m_pEnumLogEntry;

ITravelLogEntry *m_pTravalLogEntry;

IWebBrowser2* m_pWebBrowser;

public:

CIETravelLog(void);

~CIETravelLog(void);

void SetWebBrowser(IWebBrowser2* pWebBrowser);

void BuildHistoryMenu(CMenu * pMenu, unsigned char nCount, bool bForward);

void TravelTo(int nPosition);

};

 

CIETravelLog::CIETravelLog(void)

: m_pTravelLogStg(NULL), m_pEnumLogEntry(NULL), m_pTravalLogEntry(NULL), m_pWebBrowser(NULL)

{

}

 

CIETravelLog::~CIETravelLog(void)

{

if ( m_pTravelLogStg != NULL )

{

m_pTravelLogStg->Release();

}

if ( m_pEnumLogEntry != NULL )

{

m_pEnumLogEntry->Release();

}

if ( m_pTravalLogEntry != NULL )

{

m_pTravalLogEntry->Release();

}

if ( m_pWebBrowser != NULL )

{

m_pWebBrowser->Release();

}

}

 

//將瀏覽器的IWebBrowser2接口指針賦予CIETravelLog的實例

void CIETravelLog::SetWebBrowser(IWebBrowser2* pWebBrowser)

{

if ( (m_pWebBrowser == pWebBrowser) || (m_pWebBrowser == NULL) )

{

return;

}

if ( m_pWebBrowser != NULL )

{

m_pWebBrowser->Release();

}

m_pWebBrowser = pWebBrowser;

 

IServiceProvider *pSP;

HRESULT hr = m_pWebBrowser->QueryInterface(IID_IServiceProvider, (LPVOID*)&pSP);

m_pWebBrowser->Release();

if (SUCCEEDED(hr))

{

hr = pSP->QueryService(SID_STravelLogCursor, IID_ITravelLogStg, (LPVOID*)&m_pTravelLogStg);

pSP->Release();

}

}

 

//創建瀏覽歷史菜單,bForward指明是前進還是后退菜單

void CIETravelLog::BuildHistoryMenu(CMenu * pMenu, unsigned char nCount, bool bForward)

{

if ( m_pTravelLogStg == NULL )

{

return;

}

TLENUMF eFlag = bForward ? TLEF_RELATIVE_FORE : TLEF_RELATIVE_BACK;

if ( FAILED(m_pTravelLogStg->EnumEntries( eFlag, &m_pEnumLogEntry ) ) )

{

return;

}

 

ULONG uFetched;

int i=0;

if ( m_pEnumLogEntry !=NULL )

{

while ( SUCCEEDED( m_pEnumLogEntry->Next( 1, &m_pTravalLogEntry, &uFetched ) ) &&

m_pTravalLogEntry && i<10 )//我們最多只需要10條歷史菜單,可根據實際情況修改

{

LPOLESTR pszTitle;

m_pTravalLogEntry->GetTitle( &pszTitle );

CString strTitle = pszTitle;

if ( bForward )

{

//ID_IEHISTORY_MIDDLE是預定義的某個菜單項ID,從該ID開始前后可以創建10個菜單項,參見下一節

pMenu->InsertMenu( 0, MF_STRING, ID_IEHISTORY_MIDDLE + ++i, strTitle );

}

else

{

pMenu->InsertMenu( 0, MF_STRING, ID_IEHISTORY_MIDDLE - ++i, strTitle );

}

CoTaskMemFree( pszTitle );

m_pTravalLogEntry->Release();

}

}

}

 

//根據與當前頁面的相對距離來訪問歷史網頁

void CIETravelLog::TravelTo(int nPosition)

{

if ( m_pTravelLogStg == NULL )

{

return;

}

if SUCCEEDED(m_pTravelLogStg->GetRelativeEntry( nPosition, &m_pTravalLogEntry ))

{

m_pTravelLogStg->TravelTo( m_pTravalLogEntry );

}

}

 

5、使用CIETravelLog

假設是在我們自己編寫的多窗口瀏覽器中使用Travel Log。為簡單起見,我們聲明一個CIETravelLog的全局對象g_IETravelLog,以便在任何地方調用。然后在適當的地方,如CMainFrame的TBN_DROPDOWN消息(工具條菜單下拉消息)處理函數OnDropDown中,添加下面的代碼,用以創建瀏覽歷史菜單:

//GetActiveWebBrowserPtr返回活動的瀏覽器IWebBrowser2接口指針

IETravelLog.SetWebBrowser( GetActiveWebBrowserPtr );

//bForward為true則創建“前進”菜單,否則創建“后退”菜單

IETravelLog.BuildHistoryMenu( &Menu, 10, bForward);

 

以下定義為菜單項ID的范圍,前后共可以容納10個菜單項,可根據實際情況修改。

#define ID_IEHISTORY_FIRST  60200

#define ID_IEHISTORY_MIDDLE 60210

#define ID_IEHISTORY_LAST   60220

 

添加命令處理函數OnTravelHistoryUrl用以響應從ID_IEHISTORY_FIRST到ID_IEHISTORY_LAST的菜單命令。

 

ON_COMMAND_RANGE(ID_IEHISTORY_FIRST, ID_IEHISTORY_LAST, OnTravelHistoryUrl)

 

void CMainFrame::OnTravelHistoryUrl(UINT nID /* Command ID */)

{

//nID - ID_IEHISTORY_MIDDLE即為要訪問的瀏覽歷史到當前頁面的距離

g_IETravelLog.TravelTo( nID - ID_IEHISTORY_MIDDLE );

}

 

6、再談Travel Log

前面我提到“Travel Log接口正日益成為應用程序中的重要接口之一”,此處加以說明。從微軟平臺的開發模式及導向來看,基于Internet Explorer/WebBrowser Control的應用勢必會成為主流。在下一代的操作系統Longhorn中,應用程序界面的描述將完全由XML的一個特化——XAML來完成,而XAML的解析將由瀏覽器完成。微軟說未來應用程序的部署將會十分容易,本地應用和基于瀏覽器的應用之間的差異將會被逐漸淡化,而實現這一目標的一個重要表現就是,在將來的操作系統平臺上,應用程序實際上時刻都將運行在Internet Explorer中,Internet Explorer在某種程度上來說變成了一個容器。

于是,扎根于Internet Explorer的Travel Log自然而然地就被整合到了我們的應用程序中。君不見,我們每天在資源管理器和瀏覽器上完成的工作,不就是在Travel Log中來來回回地跑嗎?如果所有的應用程序都嵌入到Internet Explorer中運行,那么我們在應用程序中所作的操作便自然得到了記錄,“前進”和“后退”也就很Easy了。

很多軟件都已經或多或少地開始采用基于Internet Explorer的模式,如Microsoft Money、Microsoft Encarta、Visual Studio.net的安裝程序等等,都是很好的范例。所以,就目前來說,將我們的應用程序按這種模式編寫(可參考《利用瀏覽器實現程序界面與實現的分離》),不是可以早一點獲得“訪問日志的體驗”嗎?

何樂而不為。

 

引用地址:《Internet Explorer 編程簡述(八)實現瀏覽歷史菜單

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=308620


posted on 2007-07-29 15:22 旅途 閱讀(930) 評論(0)  編輯 收藏 引用 所屬分類: BHO

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            噜噜噜在线观看免费视频日韩| 午夜精品久久久久久久99热浪潮| 久久久7777| 激情婷婷亚洲| 麻豆成人在线| 美女主播一区| 日韩午夜av电影| 日韩天天综合| 国产女优一区| 免费av成人在线| 嫩草国产精品入口| 中文在线不卡视频| 亚洲自拍啪啪| 在线观看国产成人av片| 欧美国产日韩一区二区在线观看 | 久久成人在线| 久久人人爽人人爽| 亚洲美女在线观看| 中文一区字幕| 伊人成人在线| 日韩系列在线| 国产美女精品一区二区三区 | 国产一区二区三区四区| 美女精品国产| 欧美日韩午夜在线视频| 久久激情五月激情| 欧美激情黄色片| 午夜精品福利在线| 久久一区二区三区国产精品| 先锋亚洲精品| 日韩视频永久免费| 亚洲欧美经典视频| 亚洲日产国产精品| 亚洲欧美国产77777| 亚洲缚视频在线观看| 亚洲图片欧美日产| 91久久久国产精品| 午夜视频在线观看一区二区三区| 亚洲国产第一页| 亚洲欧美区自拍先锋| 亚洲第一网站| 欧美日韩中文| 欧美成人精品福利| 先锋影音一区二区三区| 欧美激情一区二区三区高清视频| 久久不见久久见免费视频1| 欧美日韩精品二区| 欧美成人免费在线| 国产在线播放一区二区三区| 国内久久精品| 亚洲欧美国产精品桃花| 在线一区二区三区四区五区| 久久综合九色综合网站| 久久精品国产精品亚洲综合| 欧美日韩一区在线观看| 女同性一区二区三区人了人一| 国产精品v片在线观看不卡| 亚洲国产高清自拍| 在线国产日韩| 久久精品亚洲一区| 欧美一区二区免费| 国产精品日韩欧美| 亚洲视频福利| 亚洲欧美日韩视频二区| 欧美日韩国产首页在线观看| 欧美激情第五页| 亚洲国产精品t66y| 男人的天堂亚洲| 欧美成人精品一区二区| 亚洲国产高清aⅴ视频| 久久深夜福利免费观看| 欧美xart系列高清| 亚洲国产一区二区三区青草影视| 久久影音先锋| 亚洲韩国精品一区| 99在线精品免费视频九九视| 欧美日韩国产色综合一二三四| 亚洲精品无人区| 亚洲私人影院| 国产老女人精品毛片久久| 亚洲一区欧美一区| 久久久噜噜噜久久中文字幕色伊伊| 国产在线乱码一区二区三区| 性欧美暴力猛交69hd| 久久久综合网站| 亚洲第一视频网站| 欧美日韩调教| 亚洲女同同性videoxma| 久久久久久久999| 在线免费不卡视频| 欧美区国产区| 亚洲影院免费| 免费观看国产成人| 99视频超级精品| 国产乱码精品一区二区三| 久久精品91久久久久久再现| 亚洲国产精品精华液网站| 一区二区日韩伦理片| 国产精品美女999| 久久久久国产精品一区三寸| 亚洲福利在线观看| 亚洲在线成人| 亚洲成色www久久网站| 欧美日韩成人| 午夜在线精品| 亚洲三级影片| 久久久精品国产免费观看同学| 1769国内精品视频在线播放| 欧美日韩免费精品| 久久成年人视频| 99国内精品| 欧美xx视频| 欧美在线观看一区| 亚洲精品国精品久久99热| 国产精品日韩在线观看| 欧美aⅴ一区二区三区视频| 亚洲综合日韩中文字幕v在线| 欧美成人午夜激情| 欧美有码视频| 亚洲视频免费| 亚洲高清视频一区| 国产欧美一区二区三区久久 | 亚洲卡通欧美制服中文| 久久久精品日韩| 亚洲欧美日韩国产| 亚洲精品一区二区三| 激情欧美一区| 国产欧美一区二区精品秋霞影院| 欧美日韩国产成人精品| 久久免费视频这里只有精品| 亚洲一区精品电影| 在线视频欧美日韩精品| 亚洲欧洲日本专区| 欧美黄色网络| 毛片精品免费在线观看| 欧美一区二区三区播放老司机| 亚洲理伦在线| 亚洲欧洲精品一区二区三区不卡 | 乱中年女人伦av一区二区| 亚洲在线观看视频| 亚洲日本免费| 亚洲国产精品嫩草影院| 激情文学综合丁香| 激情久久中文字幕| 韩国女主播一区二区三区| 国产精品另类一区| 欧美激情第4页| 欧美精品在线播放| 欧美日韩美女| 欧美午夜片在线免费观看| 欧美日韩日本国产亚洲在线| 欧美国产在线电影| 欧美精品福利视频| 欧美日韩国产成人在线免费| 欧美电影在线免费观看网站| 欧美成年人视频网站| 欧美r片在线| 欧美日韩一区二区在线播放| 欧美日韩国内| 国产精品青草综合久久久久99| 欧美午夜视频网站| 国产精品日日摸夜夜摸av| 国产女同一区二区| 在线观看国产成人av片| 亚洲国产成人久久综合| 99精品欧美一区| 午夜欧美理论片| 久久久久88色偷偷免费| 免费在线成人| 亚洲免费av片| 亚洲欧美在线观看| 久久蜜桃资源一区二区老牛| 欧美高清hd18日本| 国产精品久久久久久久久借妻| 国产视频精品va久久久久久| 狠狠色狠色综合曰曰| 亚洲美女av黄| 香蕉久久久久久久av网站| 麻豆成人av| 日韩视频免费观看高清在线视频| 亚洲一级片在线看| 久久久999精品| 欧美日韩精选| 国内偷自视频区视频综合| 亚洲最新合集| 久久亚洲私人国产精品va媚药| 亚洲清纯自拍| 久久av一区二区| 欧美日韩亚洲综合| 亚洲成人在线观看视频| 中文精品视频一区二区在线观看| 久久av一区二区| 亚洲经典三级| 久久精品72免费观看| 欧美日韩在线精品| 在线观看日韩www视频免费 | 国产精品系列在线| 99精品欧美一区二区蜜桃免费| 久久精品日韩欧美| 一级日韩一区在线观看|