转自:https://www.douban.com/note/181738144/
3. ipicture
IPicture的缩放效果好一点,有两种方法:1)一种是直接显示不下载图片到本地,[cpp] view plain copy HRESULT CListListBox::ShowPic(CDC* pDC,CString strImgUrl,CRect rect) { HDC hDC_Temp = pDC->GetSafeHdc(); IPicture *pPic; IStream *pStm; HRESULT bResult;// = FALSE; DWord dwFileSize,dwByteRead; //读取网页上图片文件,实际是个CHttpFile指针 CInternetsession session(L"HttpClient"); CFile* httpFile = (CFile*)session.OpenURL(strImgUrl); if (httpFile!=INVALID_HANDLE_VALUE) { dwFileSize= httpFile->GetLength();//获取文件字节数 if (dwFileSize==0xFFFFFFFF) return E_FAIL; } else { return E_FAIL; } //分配全局存储空间 HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); LPVOID pvData = NULL; if (hGlobal == NULL) return E_FAIL; if ((pvData = GlobalLock(hGlobal)) == NULL)//锁定分配内存块 return E_FAIL; //把文件读入内存缓冲区 dwByteRead = httpFile->Read(pvData,dwFileSize); GlobalUnlock(hGlobal); CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); //装入图形文件 bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic); if(FAILED(bResult)) return E_FAIL; OLE_XSIZE_HIMETRIC hmWidth; //图片的真实宽度, 单位为英寸 OLE_YSIZE_HIMETRIC hmHeight; //图片的真实高度, 单位为英寸 pPic->get_Width(&hmWidth); pPic->get_Height(&hmHeight); //转换hmWidth和hmHeight为pixels距离,1英寸=25.4毫米 int nWidth = MulDiv(hmWidth,GetDeviceCaps(hDC_Temp,LOGPIXELSX),2540); int nHeight = MulDiv(hmHeight,GetDeviceCaps(hDC_Temp,LOGPIXELSY),2540); //缩放图片 int nWZoom = nWidth / rect.Width(); int nHZoom = nHeight / rect.Height(); int nZoom = 1; nZoom = ( nWZoom > nHZoom ) ? nWZoom : nHZoom; nWidth /= nZoom; nHeight /= nZoom; int midW = (rect.left + rect.right) / 2; int midH = (rect.top + rect.bottom) / 2; rect.left = midW - nWidth / 2; rect.right = midW + nWidth / 2; rect.top = midH - nHeight / 2; rect.bottom = midH + nHeight / 2; //将图形输出到屏幕上(有点像BitBlt) bResult=pPic->Render(hDC_Temp,rect.left,rect.top,rect.Width(),rect.Height(), 0,hmHeight,hmWidth,-hmHeight,NULL); pPic->Release(); httpFile->Close();//关闭打开的文件 if (SUCCEEDED(bResult)) { return S_OK; } else { return E_FAIL; } } 2)%20一种是把图片下载后保存本地再打开。[cpp] view%20plain copy HRESULT CListListBox::ShowPic(CDC* pDC,CString strImgUrl,CRect rect) { HDC hDC_Temp = pDC->GetSafeHdc(); HRESULT bResult;// = FALSE; DWORD dwFileSize = 0,dwByteRead; CString url = strImgUrl; CString path = GetPic(strImgUrl); //if(url.Find(L".jpeg") != -1) return E_FAIL; if(path.IsEmpty()) { url = SavePic(url); //return FALSE; } else { url = path; } CFile file; if (!file.Open(url, CFile::modeRead|CFile::shareDenyWrite)) { return FALSE; } CArchive ar(&file, CArchive::load | CArchive::bNoFlushOnDelete); CArchiveStream arcstream(&ar); IPicture *pPic; IStream *pStm = (IStream*)&arcstream ; //HRESULT hr = OleLoadPicture(pStm, 0, FALSE,IID_IPicture, (LPVOID*)&pPic); //ASSERT(SUCCEEDED(hr) && m_spIPicture); //bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic); bResult=OleLoadPicture(pStm,0,FALSE,IID_IPicture,(LPVOID*)&pPic); if(FAILED(bResult)) return E_FAIL; OLE_XSIZE_HIMETRIC hmWidth; //图片的真实宽度, 单位为英寸 OLE_YSIZE_HIMETRIC hmHeight; //图片的真实高度, 单位为英寸 pPic->get_Width(&hmWidth); pPic->get_Height(&hmHeight); //转换hmWidth和hmHeight为pixels距离,1英寸=25.4毫米 int nWidth = MulDiv(hmWidth,GetDeviceCaps(hDC_Temp,LOGPIXELSX),2540); int nHeight = MulDiv(hmHeight,GetDeviceCaps(hDC_Temp,LOGPIXELSY),2540); //缩放图片 double nWZoom = nWidth / rect.Width(); double nHZoom = nHeight / rect.Height(); double nZoom = 1; nZoom = ( nWZoom > nHZoom ) ? nWZoom : nHZoom; nWidth /= nZoom; nHeight /= nZoom; int midW = (rect.left + rect.right) / 2; int midH = (rect.top + rect.bottom) / 2; CRect showRect(rect); showRect.left = ((midW - nWidth / 2) < rect.left) ? rect.left : (midW - nWidth / 2); showRect.right = ((midW + nWidth / 2) > rect.right) ? rect.right : (midW + nWidth / 2); showRect.top = ((midH - nHeight / 2) < rect.top) ? rect.top : (midH - nHeight / 2); showRect.bottom = ((midH + nHeight / 2) > rect.bottom) ? rect.bottom : (midH + nHeight / 2); if(showRect.left < 0 || showRect.right < 0 || showRect.top < 0 || showRect.bottom < 0) return E_FAIL; //将图形输出到屏幕上(有点像BitBlt) bResult=pPic->Render(hDC_Temp,showRect.left,showRect.top,showRect.Width(),showRect.Height(), 0,hmHeight,hmWidth,-hmHeight,NULL); pPic->Release(); file.Close();//关闭打开的文件 ar.Close(); arcstream.Release(); if (SUCCEEDED(bResult)) { return S_OK; } else { return E_FAIL; } } 把网络图片下载到本地还有一个小插曲,开始我使用File Open的方式读取网络图片,对于有些图片是管用的。但是GetLength得到的值有时会很小,直接导致图片下载不全,OleLoadPicture的时候程序直接卡死了。[cpp] view plain copy CString CListListBox::SavePic(CString strImgUrl) { //本地缓存路径 if(path.IsEmpty()) return L""; DWORD dwFileSize,dwByteRead; //读取网页上图片文件,实际是个CHttpFile指针 CInternetSession session(L"HttpClient"); CStdioFile* httpFile = session.OpenURL(strImgUrl); if (httpFile!=INVALID_HANDLE_VALUE) { for(int i = 0; i < 100; i++) { dwFileSize = httpFile->GetLength();//获取文件字节数 } if (dwFileSize==0xFFFFFFFF) { DWORD err = GetLastError(); return L""; } } else { return L""; } CFile file; if(file.Open(path,CFile::modeCreate|CFile::modeWrite)) { while(dwFileSize > 0) { BYTE* pvData = new BYTE[dwFileSize];//[100*1024*1024]; memset(pvData, 0, dwFileSize); dwByteRead = httpFile->Read(pvData,dwFileSize); file.Write(pvData,dwByteRead); delete pvData; dwFileSize -= dwByteRead; } } file.Close(); httpFile->Close(); session.Close(); return path; } 后来在网上搜了牛人写的程序直接拿来用,居然很好用,速度也挺快[cpp] view%20plain copy CString CListListBox::SavePic(CString strImgUrl) { DWORD length=0; BYTE buffer[1024]; memset(buffer,0,1024); HINTERNET hInternet; hInternet=InternetOpen(_T("Testing"),INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0); if (hInternet==NULL) { //cout<<_T("Internet open failed!")<<endl; return L""; } HINTERNET hUrl; hUrl=InternetOpenUrl(hInternet,strImgUrl,NULL,0,INTERNET_FLAG_RELOAD,0); if (hUrl==NULL) { // cout<<_T("Internet open url failed!")<<endl; InternetCloseHandle(hInternet); return L""; } BOOL hwrite; DWORD written; HANDLE hFile; CString path = CreateLocalPath(strImgUrl); hFile=CreateFile(path,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); if (hFile==INVALID_HANDLE_VALUE) { //cout<<_T("Create File failed!")<<endl; InternetCloseHandle(hUrl); InternetCloseHandle(hInternet); return L""; } BOOL read; while(1) { read=InternetReadFile(hUrl,buffer,sizeof(buffer),&length); if(length==0) break; hwrite=WriteFile(hFile,buffer,sizeof(buffer),&written,NULL); if (hwrite==0) { //cout<<_T("Write to file failed!")<<endl; CloseHandle(hFile); InternetCloseHandle(hUrl); InternetCloseHandle(hInternet); return L""; } } CloseHandle(hFile); InternetCloseHandle(hUrl); InternetCloseHandle(hInternet); return path; } 大功告成,由于开发时间匆忙,很多细节没有追究,等以后有时间了再补上,这里做个记录吧。新闻热点
疑难解答