用Socket和MSHTML對象模型創建自己的瀏覽器

發表于:2007-07-14來源:作者:點擊數: 標簽:
中央財經大學管理信息系 薛 瑛 HTTP協議和WEB瀏覽器的誕生給我們的 網絡 增加了更多的精彩。但在實際應用中我們可能會有不同的需要而不是單純的使用瀏覽器,譬如在我們的應用程序中加入瀏覽互聯網的功能。微軟的ChtmlView類很方便的實現了網頁瀏覽。但是它很
中央財經大學管理信息系 薛 瑛

HTTP協議和WEB瀏覽器的誕生給我們的網絡增加了更多的精彩。但在實際應用中我們可能會有不同的需要而不是單純的使用瀏覽器,譬如在我們的應用程序中加入瀏覽互聯網的功能。微軟的ChtmlView類很方便的實現了網頁瀏覽。但是它很不靈活,無法使用戶動態地在網頁上修改自己想要的元素。本文探討一些方法使用Socket傳輸Html文檔,利用微軟的動態MSHTML對象模型實現一些瀏覽器的內部機制。
大家知道HTML文檔是由標記語言構成,即俗稱的Tag。微軟的瀏覽器IE對于這些標記實現了一一對應的對象模型(objectmodel),由MSHTML.DLL封裝。IE瀏覽器的實現也是由MSHTML.DLL來實現的。通過MSHTML.DLL我們可以直接操作對象模型的屬性,方法。MSHTML的對象模型是基于COM組件對象的,對象的接口是基于Idispatch,操作MSHTML對象模型必須通過Idispatch接口。MSHTML中封裝了許多這樣的接口,例如,IhtmlAnchorElement接口對應與HTML文檔中的超連接標記<A>,IHtmlHRElement接口對應<HR>標記,IhtmlTable接口對應<table>標記。其中最重要的是IhtmlDocument2接口,它對應Document組件。Document組件既相當于HTML文檔。使用過Javascript的人對它應比較熟悉。
下面我們舉例來講解MSHTML的應用。在舉例之前我先講述一下Socket和HTTP協議。HTTP協議通過TCP連接服務器和Client,它工作在80端口。HTTP通過Client和Server之間的請求/應答機制進行通訊。HTTP消息分為Request和Response。每一種消息由開始行,消息頭和消息體組成。形式如下:
generic-message = start-line
*message-header
CRLF
[ message-body ]
?  
start-line的形式如下:
start-line = Request-Line | Status-Line
Request-Line為Client向Server發出的請求,形式如下:
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
Method 包括GET,POST等,在本例中我們只簡單的使用GET向服務器發出請求。  
詳細的HTTP協議請參考RFC2068。
在VC++中建立新的單文檔EXE工程文件,為了使用MSHTML我們的視圖類繼承自ChtmlView。ChtmlView類封裝了MSHTML接口。給工程中加入Socket類。
class CHttpSocket : public CSocket
{
………………
?  
protected:
CWnd * m_pParentWnd;
}
其中m_pParentWnd指向我們的視圖類,用于傳送消息。在視圖類中定義Socket。
class CSkhttpView : public CHtmlView
{
protected: // create from serialization only
CSkhttpView();
DECLARE_DYNCREATE(CSkhttpView)
…………….
protected:
CHttpSocket m_socket;
IHTMLDocument2 * phmDoc2;
……..
}
phmDoc2為IHTMLDocument2接口。初始化Socke,連接我們欲登錄的站點,假設為www.163.net。
CSkhttpView::CSkhttpView()
{
// TODO: add construction code here
BOOL bRet=m_socket.Create(0,SOCK_STREAM,NULL);  
if(!bRet)
MessageBox("socket create error",NULL,MB_OK);
m_socket.SetParentWnd(this);  
if(!m_socket.Connect(www.163.net,80))
MessageBox(“socket connect error”,NULL,MB_OK);
}
下面我們取得IhtmlDocument2的接口。此接口的獲得一般有兩種方法。一是使用CoCreateInstance,然后調用QueryInterface。另一種是使用MSHTML控件對象的get_Document,在ChtmlView類中封裝了這個接口。我們使用后一種。需要注意的是,我們需要在ChtmlView生成IhtmlDocument對象后才能獲得它的接口。
void CSkhttpView::OnInitialUpdate()  
{
Navigate2(“about:blank”);
}
void CSkhttpView::OnDocumentComplete(LPCTSTR lpszURL)
{
LPDISPATCH lpdisp;
HRESULT hr;
lpdisp=GetHtmlDocument();
hr=lpdisp->QueryInterface(IID_IHTMLDocument2,(void **)&phmDoc2);
}
在ChtmlView初始化時調用Navigate2()產生空文檔,文檔產生后調用GetHtmlDocument獲得一個Idispatch()接口,調用QueryInterface獲得IHTMLDocument2接口。
void CSkhttpView::OnReceiveMessage(WPARAM wParam,LPARAM lParam)
{
HRESULT hr;
char buf[5000];
int inum;
IHTMLElement * pEleBody;
if(wParam==0)
{
inum=m_socket.Receive(buf,sizeof(buf),0);
buf[inum]=0;
_bstr_t bsrBody(buf);
hr=phmDoc2->get_body(&pEleBody);
hr=pEleBody->put_innerHTML(bsrBody);  
}
}  
?  
void CSkhttpView::OnControlSend()  
{
// TODO: Add your command handler code here
char buf[1000];
wsprintf(buf,"GET http://www.163.net HTTP/1.1\r\n\r\n");
int iRet=m_socket.Send(buf,lstrlen(buf),0);
if(iRet==SOCKET_ERROR)
MessageBox(“socket send error”,NULL,MB_OK);
}
我們向服務器發送HTTP協議的請求”GET http://www.163.net HTTP/1.1\r\n\r\n”,它取回指定URI地址的網頁。服務器發出回應我們通過Socket接受。IhtmlDocument2內含許多對象借口,通過許多的put_,get_方法我們可以獲得這些對象的屬性,事件,方法。本例中我們獲得body對象,它對應于HTML文擋中<body></body>對象。通過IhtmlDocument2的get_body()得到指定body對象的IHTMLElement接口,調用IHTMLElement接口的put_innerHTML()將接受到的內容放入Document中。此時在我們的視圖中就會顯示網頁。
本文只是簡略的介紹了一下MSHTML對象,它里面實際包含了許多的接口和函數,通過這些接口我們可以任意設計我們自己風格的瀏覽器。有興趣的同志可以參閱MSDN文檔。 

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97