转自:https://www.douban.com/note/181738144/
3. IPicture
IPicture的缩放效果好一点,有两种方法:1)一种是直接显示不下载图片到本地,
- 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) 一种是把图片下载后保存本地再打开。
- 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的时候程序直接卡死了。
- 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;
- }
后来在网上搜了牛人写的程序直接拿来用,居然很好用,速度也挺快
- 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;
- }
大功告成,由于开发时间匆忙,很多细节没有追究,等以后有时间了再补上,这里做个记录吧。