BEGIN_INTERFACE_PART(HttpNegotiateObj, IHttpNegotiate)
STDMETHOD_(HRESULT, BeginningTransaction)(LPCWSTR szUrl,
LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
STDMETHOD_(HRESULT, OnResponse)(DWORD dwResponseCode,
LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR*
pszAdditionalRequestHeaders)
END_INTERFACE_PART(HttpNegotiateObj)
3.
使用 MFC 的 BEGIN_INTERFACE_MAP 宏将 IHttpNegotiate 添加为一个 QI-able 接口。这应该位于该类的 .cpp 文件中。
BEGIN_INTERFACE_MAP(NegotiateCallback, CCmdTarget)
INTERFACE_PART(NegotiateCallback, IID_INegotiateCallback, Dispatch)
INTERFACE_PART(NegotiateCallback, IID_IHttpNegotiate, HttpNegotiateObj)
END_INTERFACE_MAP()
4.
提供 IHttpNegotiate 方法的实现,以便添加标头或检查响应标头。下面的代码会向传出事务添加一个 X-Custom-App HTTP 标头。请注意,您要负责在每个自定义标头的结尾插入一个 CR/LF(回车符/换行符);否则,您的自定义标头则会省略后面紧跟的标头,从而损坏您的 HTTP 事务。另外,还要确保使用 CoTaskMemAlloc() 来代替 C 运行库内存管理函数,以便 URLMON 可以通过调用 CoTaskMemFree() 来释放您的数据。
STDMETHODIMP NegotiateCallback::XHttpNegotiateObj::BeginningTransaction(LPCWSTR
szUrl, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR
*pszAdditionalHeaders) {
LPWSTR pszHeader = (LPWSTR)CoTaskMemAlloc(74)
memcpy((void*)pszHeader, (void*)L"X-Custom-App: Version
1.1.3748.9\r\n", 74)
*pszAdditionalHeaders=pszHeader
return S_OK
}
5.
创建一个新的 MFC 类,使其成为 CAsyncMonikerFile 的子类。我们将此类称为 CFetchData。
6.
重写 CAsyncMonikerFile 的 Open() 方法。此方法负责创建 MFC 用于接收下载状态事件的 IBindStatusCallback 实现。您需要使用一个指向 NegotiateCallback 的 IUnknown 的指针自己创建此回调,从而使得 MFC 的 IBindStatusCallback 实现和您的 IHttpNegotiate 实现能够得以聚合。聚合是一个 COM 技术,它能够使用一个类的功能来扩展另一个类。在此实例中,这就表示 URLMON 为 IHttpNegotiate 在 MFC 的 IBindStatusCallback 上执行的所有查询都将委托给您的 IHttpNegotiate 实现。
BOOL CFetchData::Open(LPCTSTR lpszURL, CFileException* pError) {
nc = new NegotiateCallback()
LPDISPATCH pNegCallDisp = nc->GetIDispatch(FALSE)
// I borrowed this from oleasmon.cpp.
IPTR(IBindHost) pBindHost(CreateBindHost(), FALSE)
IPTR(IBindCtx) pBindCtx(CreateBindContext(pError), FALSE)
if (pError &&(pError->m_cause != CFileException::none))
return FALSE
// Instantiate our NegotiateCallback object, and aggregate with the
// IBindStatusCallback supplied by MFC.
IPTR(IUnknown) pBSCUnk(CreateBindStatusCallback(pNegCallDisp), FALSE)
IPTR(IBindStatusCallback) pBSC
pBSCUnk->AddRef()
pBSC.QueryInterface(pBSCUnk)
return Attach(lpszURL, pBindHost, pBSC, pBindCtx, pError)
}
7.
为了在数据下载后接收数据,请在 CAsyncMonikerFile 上实现 IBindStatusCallback 方法。CAsyncMonikerFile 已经实现了此接口,因此您只需提供重写。
HTTP请求方式有两种,一种是GET方式,请求参数会用“?”作为分隔符跟在请求资源后面;另一种是POST方式,请求参数放在了最后面的位置。服务器监听到浏览器的链接,首先将HTTP请求信息保存下来,再进行解析。//请求信息的输入流privateInputStreaminput//获得HTTP请求信息,并解析出请求使用的是GET还是POST,然后调用相应的处理方法进行处理publicvoidparseInput(){byte[]b=newbyte[1024]try{input.read(b)}catch(IOExceptione){LogInfo.error("读取请求信息出错"+e.getMessage())return}StringinputStr=newString(b)Stringtype=inputStr.substring(0,inputStr.indexOf(""))if("GET".equals(type)){parseGetString(inputStr)}else{parsePostString(inputStr)}}//路径信息,解析GET请求publicvoidparseGetString(StringgetStr){StringallStr=getStrStringinfo=allStr.substring(allStr.indexOf("/"),allStr.indexOf("HTTP"))intend=info.indexOf("?")if(end==-1){pathInfo=info}else{pathInfo=info.substring(0,end)queryStr=info.substring(end+1)}urlPattern=pathInfo.substring(pathInfo.lastIndexOf("/"))parseQueryInfo(queryStr)}//解析POST请求publicvoidparsePostString(StringpostStr){StringqStr=postStr.trim()pathInfo=postStr.substring(postStr.indexOf("/"),postStr.indexOf("HTTP"))urlPattern=pathInfo.substring(pathInfo.lastIndexOf("/"))queryStr=qStr.substring(qStr.lastIndexOf(System.getProperty("line.separator"))).trim()parseQueryInfo(queryStr)}解析出请求资源路径和请求参数就可以找到对应的资源发送给浏览器或根据请求参数做相应的处理,再将资源发送回去。方法参考如下:private boolean mRestoringBookmark
private float mScrollY
@SuppressWarnings("deprecation")
protected void onPageFinished() {
if (mRestoringBookmark) {
setPictureListener(mPictureListener)
mRestoringBookmark = false
}
}
@SuppressWarnings("deprecation")
private PictureListener mPictureListener = new PictureListener() {
@Override
public void onNewPicture(WebView view, Picture picture) {
// stop listening
setPictureListener(null)
scrollTo(0, (int)(getContentHeight() * mScrollY))
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)