我在eMbedded Visual C++下编写一个浏览器的程序,这个浏览器要求可以访问html页面,处理点击链接事件,显示图片。
要求是从底层传输做起。
我是这样做的,先发送http请求,获取页面,然后存储到缓冲区里。
如下
int CFlyIEDlg::DownloadPage(LPTSTR szAddress)
{
int   nRetCode = 0;
DWORD dwAccessType = PRE_CONFIG_INTERNET_ACCESS;
const TCHAR szHeaders[] = _T("Accept: text/*\r\nUser-Agent: MFC_Http_Sample\r\n");
DWORD dwHttpRequestFlags = INTERNET_FLAG_NO_AUTO_REDIRECT;
BOOL  bSuccess = TRUE; CInternetSession session(CString((LPCTSTR)IDS_HTTPAPP), (DWORD)this, dwAccessType);
CHttpConnection* pServer = NULL;
CHttpFile* pFile = NULL;
TRY
{
// check to see if this is a reasonable URL
CString strServerName;
CString strObject;
INTERNET_PORT nPort;
DWORD dwServiceType; if (!AfxParseURL(szAddress, dwServiceType, strServerName, strObject, nPort) || 
dwServiceType != INTERNET_SERVICE_HTTP)
{
SetDlgItemText(IDC_EDIT_PAGE, CString((LPCTSTR)IDS_ERROR1));
ThrowHttpException(kError1);
} session.EnableStatusCallback(TRUE); pServer = session.GetHttpConnection(strServerName, nPort); pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject, NULL, (DWORD)this, NULL, NULL, dwHttpRequestFlags);
pFile->AddRequestHeaders(szHeaders);
pFile->SendRequest(); DWORD dwRet;
pFile->QueryInfoStatusCode(dwRet); if (dwRet == HTTP_STATUS_DENIED)
{
MessageBox (L"Access to the secured http site is denied!", L"Error", MB_OK);
return 0;
} CString strNewLocation;
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation); // were we redirected?
// these response status codes come from WININET.H if (dwRet == HTTP_STATUS_MOVED ||
dwRet == HTTP_STATUS_REDIRECT ||
dwRet == HTTP_STATUS_REDIRECT_METHOD)
{
CString strNewLocation;
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation); int nPlace = strNewLocation.Find(_T("Location: "));
if (nPlace == -1)
{
SetDlgItemText(IDC_EDIT_PAGE, CString((LPCTSTR)IDS_ERROR2) );
ThrowHttpException(kError2);
} strNewLocation = strNewLocation.Mid(nPlace + 10);
nPlace = strNewLocation.Find('\n');
if (nPlace > 0)
strNewLocation = strNewLocation.Left(nPlace); // close up the redirected site pFile->Close();
delete pFile;
pServer->Close();
delete pServer; CString csMsg = CString((LPCTSTR)IDS_CAUTION) + strNewLocation; // figure out what the old place was
if (!AfxParseURL(strNewLocation, dwServiceType, strServerName, strObject, nPort))
{
SetDlgItemText(IDC_EDIT_PAGE, CString((LPCTSTR)IDS_ERROR3));
ThrowHttpException(kError2);
} if (dwServiceType != INTERNET_SERVICE_HTTP)
{
SetDlgItemText(IDC_EDIT_PAGE, CString((LPCTSTR)IDS_ERROR4));
ThrowHttpException(kError2);
} // try again at the new location
pServer = session.GetHttpConnection(strServerName, nPort);
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,
strObject, NULL, (DWORD)this, NULL, NULL, dwHttpRequestFlags);
pFile->AddRequestHeaders(szHeaders);
pFile->SendRequest(); pFile->QueryInfoStatusCode(dwRet);
if (dwRet != HTTP_STATUS_OK)
ThrowHttpException(kError2);
} TCHAR* szWEBPage = new TCHAR[MAX_WEBPAGE_SIZE+1];
if(szWEBPage)
{
szWEBPage[0] = L'\0'; TCHAR* sz     = new TCHAR[BUFFER_SIZE+1];
TCHAR* szwBuf = new TCHAR[(BUFFER_SIZE+1)*2]; sz[0] = L'\0';
szwBuf[0] = L'\0';
int n = 0;
pFile->SetReadBufferSize(BUFFER_SIZE*2);
while (pFile->ReadString(sz, BUFFER_SIZE))
{
wce_AsciiToWide(szwBuf, (const char*)sz); n += _tcslen(szwBuf);
if(n >= MAX_WEBPAGE_SIZE)
break;
_tcscat(szWEBPage, szwBuf);
}
delete [] sz;
delete [] szwBuf;
SetDlgItemText(IDC_EDIT_PAGE, szWEBPage);
} delete [] szWEBPage;
pFile->Close();
pServer->Close();
}
CATCH (CInternetException,  pEx)
{
// catch things wrong with parameters, etc
if (pEx->m_dwError < kErrorMin)
{
TCHAR szError[MAX_PATH]=TEXT("\0");
pEx->GetErrorMessage(szError,MAX_PATH,NULL);
SetDlgItemText(IDC_EDIT_PAGE, szError);
}
bSuccess = FALSE;
}
AND_CATCH (CMemoryException,  pMemory)
{
// catch things wrong with memory
SetDlgItemText(IDC_EDIT_PAGE,CString((LPCTSTR)IDS_MEMORYEXCEPTION));
pMemory->Delete();
bSuccess = FALSE;
}
END_CATCH_ALL if (pFile != NULL)
delete pFile;
if (pServer != NULL)
delete pServer;
session.Close(); return nRetCode;
}然后再使用一个evc下的控件htmlview来显示html文档,和显示图片:LRESULT CFlyIEDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
switch(message)
{
case WM_NOTIFY:
NM_HTMLVIEW * pnmHTML = (NM_HTMLVIEW *) lParam;
LPNMHDR pnmh = (LPNMHDR) &(pnmHTML->hdr);
CString strReg = _T("register"); switch(pnmh->code)
      
{
case NM_HOTSPOT:
OnLink(pnmHTML->szTarget);
break;
case NM_INLINE_IMAGE:
CString strSrcText = pnmHTML->szTarget;
DWORD dwCookieValue = pnmHTML->dwCookie; CBitmap* pBitmap;
if (! m_imagesCache.Lookup(strSrcText, (CObject*&)pBitmap)) {
::SendMessage(m_hwndHtml, DTM_IMAGEFAIL, 0, (LPARAM)(LPINLINEIMAGEINFO)dwCookieValue);
break;
}
INLINEIMAGEINFO imageInfo;
imageInfo.dwCookie = dwCookieValue;
imageInfo.bOwnBitmap = FALSE;
imageInfo.hbm = (HBITMAP)(*pBitmap);
CSize size = pBitmap->GetBitmapDimension();
imageInfo.iOrigWidth = size.cx;
imageInfo.iOrigHeight = size.cy;
::SendMessage(m_hwndHtml, DTM_SETIMAGE, 0, (LPARAM)(LPINLINEIMAGEINFO)&imageInfo);
CString data;
data.Format(L"Image width=%d, height=%d, pBitmap=%p, pic name=%s", size.cx, size.cy, pBitmap, (LPCTSTR)strSrcText);
break;
}
} return CDialog::WindowProc(message, wParam, lParam);
}
现在我的问题主要有两个:1。我想点击email地址的时候,能够出现pmail(在wince下类似于outlook的),
并且出现用户的地址。请问如何做?是用shellexcute吗?那用户的email地址的字符串应该赋值给哪个参数???????????2。怎样获取页面上的图片,因为传输过程中我没有传输图片,只是把html文件传输到缓冲区,然后调用函数显示的。所以对图片的处理,还是不知道如何做?请高手指教。 如果可以的话,请留下您的email.