MFC显示网络图片_3

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;
}


大功告成,由于开发时间匆忙,很多细节没有追究,等以后有时间了再补上,这里做个记录吧。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值