MFC显示网络图片_IPicture

来源:互联网 发布:linux启动数据库命令 编辑:程序博客网 时间:2024/06/06 19:40

转自:https://www.douban.com/note/181738144/

3. IPicture

IPicture的缩放效果好一点,有两种方法:
1)一种是直接显示不下载图片到本地,
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. HRESULT CListListBox::ShowPic(CDC* pDC,CString strImgUrl,CRect rect)  
  2. {  
  3.     HDC hDC_Temp = pDC->GetSafeHdc();  
  4.     IPicture *pPic;  
  5.     IStream *pStm;  
  6.     HRESULT bResult;// = FALSE;  
  7.     DWORD dwFileSize,dwByteRead;  
  8.   
  9.     //读取网页上图片文件,实际是个CHttpFile指针  
  10.     CInternetSession session(L"HttpClient");  
  11.     CFile* httpFile = (CFile*)session.OpenURL(strImgUrl);  
  12.     if (httpFile!=INVALID_HANDLE_VALUE)  
  13.     {  
  14.         dwFileSize= httpFile->GetLength();//获取文件字节数  
  15.         if (dwFileSize==0xFFFFFFFF)  
  16.             return E_FAIL;  
  17.     }  
  18.     else  
  19.     {  
  20.         return E_FAIL;  
  21.     }  
  22.   
  23.     //分配全局存储空间  
  24.     HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);  
  25.     LPVOID pvData = NULL;  
  26.     if (hGlobal == NULL)  
  27.         return E_FAIL;  
  28.     if ((pvData = GlobalLock(hGlobal)) == NULL)//锁定分配内存块  
  29.         return E_FAIL;  
  30.   
  31.     //把文件读入内存缓冲区  
  32.     dwByteRead = httpFile->Read(pvData,dwFileSize);  
  33.     GlobalUnlock(hGlobal);  
  34.     CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);  
  35.   
  36.           
  37.     //装入图形文件  
  38.     bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic);  
  39.     if(FAILED(bResult))  
  40.         return E_FAIL;  
  41.   
  42.     OLE_XSIZE_HIMETRIC hmWidth; //图片的真实宽度, 单位为英寸  
  43.     OLE_YSIZE_HIMETRIC hmHeight; //图片的真实高度, 单位为英寸  
  44.     pPic->get_Width(&hmWidth);  
  45.     pPic->get_Height(&hmHeight);  
  46.   
  47.           
  48.     //转换hmWidth和hmHeight为pixels距离,1英寸=25.4毫米  
  49.     int nWidth = MulDiv(hmWidth,GetDeviceCaps(hDC_Temp,LOGPIXELSX),2540);  
  50.     int nHeight = MulDiv(hmHeight,GetDeviceCaps(hDC_Temp,LOGPIXELSY),2540);  
  51.   
  52.          
  53.    //缩放图片  
  54.     int nWZoom = nWidth / rect.Width();  
  55.     int nHZoom = nHeight / rect.Height();  
  56.     int nZoom = 1;  
  57.     nZoom = ( nWZoom > nHZoom ) ? nWZoom : nHZoom;  
  58.     nWidth /= nZoom;  
  59.     nHeight /= nZoom;  
  60.     int midW = (rect.left + rect.right) / 2;  
  61.     int midH = (rect.top + rect.bottom) / 2;  
  62.     rect.left = midW - nWidth / 2;  
  63.     rect.right = midW + nWidth / 2;  
  64.     rect.top = midH - nHeight / 2;  
  65.     rect.bottom = midH + nHeight / 2;  
  66.           
  67.     //将图形输出到屏幕上(有点像BitBlt)  
  68.     bResult=pPic->Render(hDC_Temp,rect.left,rect.top,rect.Width(),rect.Height(),  
  69.         0,hmHeight,hmWidth,-hmHeight,NULL);  
  70.   
  71.     pPic->Release();  
  72.     httpFile->Close();//关闭打开的文件  
  73.   
  74.     if (SUCCEEDED(bResult))  
  75.     {  
  76.         return S_OK;  
  77.     }  
  78.     else  
  79.     {  
  80.         return E_FAIL;  
  81.     }  
  82.   
  83. }  


2) 一种是把图片下载后保存本地再打开。
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. HRESULT CListListBox::ShowPic(CDC* pDC,CString strImgUrl,CRect rect)  
  2. {  
  3.     HDC hDC_Temp = pDC->GetSafeHdc();  
  4.     HRESULT bResult;// = FALSE;  
  5.     DWORD dwFileSize = 0,dwByteRead;  
  6.     CString url = strImgUrl;  
  7.     CString path = GetPic(strImgUrl);  
  8.     //if(url.Find(L".jpeg") != -1) return E_FAIL;  
  9.     if(path.IsEmpty())  
  10.     {  
  11.         url = SavePic(url);  
  12.                 //return FALSE;  
  13.     }  
  14.     else  
  15.     {  
  16.         url = path;  
  17.     }  
  18.     CFile file;  
  19.     if (!file.Open(url, CFile::modeRead|CFile::shareDenyWrite))  
  20.     {  
  21.         return FALSE;  
  22.     }  
  23.   
  24.     CArchive ar(&file, CArchive::load | CArchive::bNoFlushOnDelete);  
  25.     CArchiveStream arcstream(&ar);  
  26.     IPicture *pPic;  
  27.     IStream *pStm = (IStream*)&arcstream ;  
  28.   
  29.         //HRESULT hr = OleLoadPicture(pStm, 0, FALSE,IID_IPicture, (LPVOID*)&pPic);  
  30.         //ASSERT(SUCCEEDED(hr) && m_spIPicture);  
  31.   
  32.     //bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic);  
  33.     bResult=OleLoadPicture(pStm,0,FALSE,IID_IPicture,(LPVOID*)&pPic);  
  34.     if(FAILED(bResult))  
  35.         return E_FAIL;  
  36.     OLE_XSIZE_HIMETRIC hmWidth; //图片的真实宽度, 单位为英寸  
  37.     OLE_YSIZE_HIMETRIC hmHeight; //图片的真实高度, 单位为英寸  
  38.     pPic->get_Width(&hmWidth);  
  39.     pPic->get_Height(&hmHeight);  
  40.   
  41.     //转换hmWidth和hmHeight为pixels距离,1英寸=25.4毫米  
  42.     int nWidth = MulDiv(hmWidth,GetDeviceCaps(hDC_Temp,LOGPIXELSX),2540);  
  43.     int nHeight = MulDiv(hmHeight,GetDeviceCaps(hDC_Temp,LOGPIXELSY),2540);  
  44.   
  45.     //缩放图片  
  46.     double nWZoom = nWidth / rect.Width();  
  47.     double nHZoom = nHeight / rect.Height();  
  48.     double nZoom = 1;  
  49.     nZoom = ( nWZoom > nHZoom ) ? nWZoom : nHZoom;  
  50.     nWidth /= nZoom;  
  51.     nHeight /= nZoom;  
  52.     int midW = (rect.left + rect.right) / 2;  
  53.     int midH = (rect.top + rect.bottom) / 2;  
  54.     CRect showRect(rect);  
  55.     showRect.left = ((midW - nWidth / 2) < rect.left) ? rect.left : (midW - nWidth / 2);  
  56.     showRect.right = ((midW + nWidth / 2) > rect.right) ? rect.right : (midW + nWidth / 2);  
  57.     showRect.top = ((midH - nHeight / 2) < rect.top) ? rect.top : (midH - nHeight / 2);  
  58.     showRect.bottom = ((midH + nHeight / 2) > rect.bottom) ? rect.bottom : (midH + nHeight / 2);  
  59.     if(showRect.left < 0 || showRect.right < 0 || showRect.top < 0 || showRect.bottom < 0) return E_FAIL;  
  60.     //将图形输出到屏幕上(有点像BitBlt)  
  61.     bResult=pPic->Render(hDC_Temp,showRect.left,showRect.top,showRect.Width(),showRect.Height(),  
  62.         0,hmHeight,hmWidth,-hmHeight,NULL);  
  63.     pPic->Release();  
  64.   
  65.     file.Close();//关闭打开的文件  
  66.     ar.Close();  
  67.     arcstream.Release();  
  68.     if (SUCCEEDED(bResult))  
  69.     {  
  70.         return S_OK;  
  71.     }  
  72.     else  
  73.     {  
  74.         return E_FAIL;  
  75.     }  
  76.   
  77. }  


把网络图片下载到本地还有一个小插曲,开始我使用File Open的方式读取网络图片,对于有些图片是管用的。但是GetLength得到的值有时会很小,直接导致图片下载不全,OleLoadPicture的时候程序直接卡死了。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CString CListListBox::SavePic(CString strImgUrl)  
  2. {  
  3.     //本地缓存路径  
  4.     if(path.IsEmpty())  
  5.         return L"";  
  6.     DWORD dwFileSize,dwByteRead;  
  7.   
  8.     //读取网页上图片文件,实际是个CHttpFile指针  
  9.     CInternetSession session(L"HttpClient");  
  10.     CStdioFile* httpFile = session.OpenURL(strImgUrl);  
  11.     if (httpFile!=INVALID_HANDLE_VALUE)  
  12.     {  
  13.         for(int i = 0; i < 100; i++)  
  14.         {  
  15.             dwFileSize = httpFile->GetLength();//获取文件字节数  
  16.         }  
  17.         if (dwFileSize==0xFFFFFFFF)  
  18.         {  
  19.             DWORD err = GetLastError();  
  20.             return L"";  
  21.         }  
  22.     }  
  23.     else  
  24.     {  
  25.         return L"";  
  26.     }  
  27.   
  28.     CFile file;  
  29.     if(file.Open(path,CFile::modeCreate|CFile::modeWrite))  
  30.     {  
  31.         while(dwFileSize > 0)  
  32.         {  
  33.             BYTE* pvData = new BYTE[dwFileSize];//[100*1024*1024];  
  34.             memset(pvData, 0, dwFileSize);  
  35.             dwByteRead = httpFile->Read(pvData,dwFileSize);  
  36.             file.Write(pvData,dwByteRead);  
  37.             delete pvData;  
  38.             dwFileSize -= dwByteRead;  
  39.         }  
  40.     }  
  41.     file.Close();  
  42.     httpFile->Close();  
  43.     session.Close();  
  44.     return path;  
  45. }  




后来在网上搜了牛人写的程序直接拿来用,居然很好用,速度也挺快
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CString CListListBox::SavePic(CString strImgUrl)  
  2. {  
  3.     DWORD length=0;  
  4.     BYTE buffer[1024];  
  5.     memset(buffer,0,1024);  
  6.     HINTERNET hInternet;  
  7.   
  8.     hInternet=InternetOpen(_T("Testing"),INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);  
  9.     if (hInternet==NULL)  
  10.     {  
  11.         //cout<<_T("Internet open failed!")<<endl;  
  12.         return L"";  
  13.     }  
  14.   
  15.     HINTERNET hUrl;  
  16.     hUrl=InternetOpenUrl(hInternet,strImgUrl,NULL,0,INTERNET_FLAG_RELOAD,0);  
  17.     if (hUrl==NULL)  
  18.     {  
  19.         // cout<<_T("Internet open url failed!")<<endl;  
  20.         InternetCloseHandle(hInternet);  
  21.         return L"";  
  22.     }  
  23.   
  24.     BOOL hwrite;  
  25.     DWORD written;  
  26.     HANDLE hFile;  
  27.         CString path = CreateLocalPath(strImgUrl);  
  28.         hFile=CreateFile(path,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);  
  29.     if (hFile==INVALID_HANDLE_VALUE)  
  30.     {  
  31.         //cout<<_T("Create File failed!")<<endl;  
  32.         InternetCloseHandle(hUrl);  
  33.         InternetCloseHandle(hInternet);  
  34.         return L"";  
  35.     }  
  36.   
  37.     BOOL read;  
  38.     while(1)  
  39.     {  
  40.         read=InternetReadFile(hUrl,buffer,sizeof(buffer),&length);  
  41.         if(length==0)  
  42.             break;  
  43.         hwrite=WriteFile(hFile,buffer,sizeof(buffer),&written,NULL);  
  44.         if (hwrite==0)  
  45.         {  
  46.             //cout<<_T("Write to file failed!")<<endl;  
  47.             CloseHandle(hFile);  
  48.             InternetCloseHandle(hUrl);  
  49.             InternetCloseHandle(hInternet);  
  50.             return L"";  
  51.         }  
  52.     }  
  53.     CloseHandle(hFile);  
  54.     InternetCloseHandle(hUrl);  
  55.     InternetCloseHandle(hInternet);  
  56.     return path;  
  57. }  


大功告成,由于开发时间匆忙,很多细节没有追究,等以后有时间了再补上,这里做个记录吧。
0 0
原创粉丝点击