1下面我们举例来讲解MSHTML的应用。在举例之前我先讲述一下Socket和HTTP协议。HTTP协议通过TCP连接服务器和Client,它工作在80端口。HTTP通过Client和Server之间的请求/应答机制进行通讯。HTTP消息分为Request和Response。每一种消息由开始行,消息头和消息体组成。形式如下:
2generic-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类。
3class 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; ……..
4} 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); }
5下面我们取得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) {
6HRESULT 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); } }
7void 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); }