1、利用IPicture接口加载、显示图片

IPicture接口管理一个图片对象和它的属性。图片对象提供对Bitmap Icon Metafile的语言不相关的抽象支持。图像对象的主要接口是IPicture和IPictureDisp。IPictureDisp从IDispatch继承,提供了通过自动化访问图片属性的能力。图片对象可通过OleCreatePictureIndirect创建。关于IPicture支持的其他接口和方法可以看MSDN,一般创建图片对象可以用OleLoadPicture函数,它简化了基于流内容创建图片对象。

IPicture接口管理一个图片对象和它的属性。图片对象提供对Bitmap Icon Metafile的语言不相关的抽象支持。图像对象的主要接口是IPicture和IPictureDisp。IPictureDisp从IDispatch继承,提供了通过自动化访问图片属性的能力。图片对象可通过OleCreatePictureIndirect创建。关于IPicture支持的其他接口和方法可以看MSDN,一般创建图片对象可以用OleLoadPicture函数,它简化了基于流内容创建图片对象。下面的代码中有两个未定义的变量是FilePath和hDC。

//FilePath是从外部传入的图片路径

//打开文件

HANDLE hFile = CreateFile(FilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

_ASSERTE(INVALID_HANDLE_VALUE != hFile);

//取文件大小

DWORD dwFileSize = GetFileSize(hFile, NULL);

_ASSERTE(-1 != dwFileSize);

LPVOID pvData = NULL;

//分配内存,准备读入图片文件的数据

//GlobalAlloc从堆分配指定字节的内存区域

HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);

_ASSERTE(NULL != hGlobal);

//GlobalLock函数锁住一个全局的内存对象同时返回一个指向对象首字节的指针

pvData = GlobalLock(hGlobal);

_ASSERTE(NULL != pvData);

DWORD dwBytesRead = 0;

//读取文件的数据到分配的全局内存

BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);

_ASSERTE(FALSE != bRead);

GlobalUnlock(hGlobal);

CloseHandle(hFile);

//到此,我们已经把文件的数据读到了内存当中

LPSTREAM pstm = NULL;

//从全局内存创建IStream接口指针

HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);

_ASSERTE(SUCCEEDED(hr) && pstm);

//根据图片文件创建IPicture接口指针

hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&gpPicture);

_ASSERTE(SUCCEEDED(hr) && gpPicture); 

pstm->Release();

//至此,IPicture接口建立好,下面开始画图片

//hDC是外部传入的画图设备

long hmWidth;

long hmHeight;

gpPicture->get_Width(&hmWidth);

gpPicture->get_Height(&hmHeight);

//转换himetric距离为pixels距离,1英寸=25.4毫米

int nWidth = MulDiv(hmWidth, GetDeviceCaps(hDC, LOGPIXELSX), 2540);

int nHeight = MulDiv(hmHeight, GetDeviceCaps(hDC, LOGPIXELSY), 2540);

RECT rc;

GetClientRect(hWnd, &rc);

//IPicture::Render显示图片

gpPicture->Render(hDC, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc);

2、C++如何调用图片
有很多办法 ,比如用IPicture,用CBitmap //MFC,更直接的是,用File进行文件操作,用BitBlt显示,具体代码你用以上关键字Google下 
这里给你推荐几个,末尾给你附一个网上可以找到的CPicture类(需MFC支持): 
-------IPicture 
// pDoc为文档对象指针 
// pDC为设备描述表指针 

::CoInitialize(NULL); // COM 初始化 
HRESULT hr; 
CFile file; 

file.Open(pDoc->GetPathName(), CFile::modeRead | CFile::shareDenyNone ); // 读入文件内容 
DWORD dwSize = file.GetLength(); 
HGLOBAL hMem = ::GlobalAlloc( GMEM_MOVEABLE, dwSize ); 
LPVOID lpBuf = ::GlobalLock( hMem ); 
file.ReadHuge( lpBuf, dwSize ); 
file.Close(); 
::GlobalUnlock( hMem ); 

IStream * pStream = NULL; 
IPicture * pPicture = NULL; 

// 由 HGLOBAL 得到 IStream,参数 TRUE 表示释放 IStream 的同时,释放内存 
hr = ::CreateStreamOnHGlobal( hMem, TRUE, &pStream ); 
ASSERT ( SUCCEEDED(hr) ); 

hr = ::OleLoadPicture( pStream, dwSize, TRUE, IID_IPicture, ( LPVOID * )&pPicture ); 
ASSERT(hr==S_OK); 

long nWidth,nHeight; // 宽高,MM_HIMETRIC 模式,单位是0.01毫米 
pPicture->get_Width( &nWidth ); // 宽 
pPicture->get_Height( &nHeight ); // 高 

CRect rect; 
GetClientRect(&rect); 

CSize sz( nWidth, nHeight ); 
pDC->HIMETRICtoDP( &sz ); // 转换 MM_HIMETRIC 模式单位为 MM_TEXT 像素单位 
long x, y, cx, cy; 

// 原始大小 
/* 
cx = sz.cx; 
cy = sz.cy; 
x = rect.Width() / 2 - cx / 2; 
y = rect.Height() / 2 - cy / 2; 
*/ 

// 自动适应窗口 
double fRatePic, fRateWnd; 
fRatePic = (double)sz.cx / (double)sz.cy; 
fRateWnd = (double)rect.Width() / (double)rect.Height(); 
if (fRatePic > fRateWnd) 

cx = rect.Width(); 
cy = (long)(rect.Width() / fRatePic); 

else 

cx = (long)(rect.Height() * fRatePic); 
cy = rect.Height(); 

if (cx == rect.Width()) 

x = 0; 
y = rect.Height() / 2 - cy / 2; 

if (cy == rect.Height()) 

x = rect.Width() / 2 - cx / 2; 
y = 0; 


pPicture->Render(pDC->m_hDC, x, y, cx, cy, 
0, nHeight, nWidth, -nHeight, NULL); 

if ( pPicture ) pPicture->Release();// 释放 IPicture 指针 
if ( pStream ) pStream->Release(); // 释放 IStream 指针,同时释放了 hMem 

::CoUninitialize(); 

--------------------------------CBitmap: 
HBITMAP bitmap; 
bitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),strFileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
m_backBitmap.DeleteObject(); 
if(!m_backBitmap.Attach(bitmap)) 

MessageBox("导入背景图失败!","提示",MB_OK); 
return; 


----------------------File:略 
前提是你要知道图片的编码格式 
一般比较简单的是BMP,包括 
BITMAPFILEHEADER,BITMAPINFO,BITMAPINFOHEADER 
如果图片采用了压缩算法可能会麻烦一点, 
关于详细情况你也以Google一下 

附CPicture(引用自网上) 

// Picture.h: interface for the CPicture 
#ifndef PICTURE_H 
#ifndef picture_h 

#define PICTURE_H 
#define picture_h 

#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 

class CPicture 

public: 
CPicture(); 
virtual ~CPicture(); 

public: 
BOOL LoadPicture(UINT nResource, LPCTSTR lpszResType) 
{return LoadPicture(MAKEINTRESOURCE(nResource), lpszResType);} 
BOOL LoadPictureFromFile(LPCTSTR lpszFileName); 
BOOL LoadPicture(LPCTSTR lpszResource,LPCTSTR lpszResType); 
BOOL IsValid(){ return m_pPic!=NULL;} 
CSize GetSize(){return m_size;} 
void Draw(CDC* pDC, LPCRECT lprcDest, LPCRECT lprcSrc); 
void Draw(CDC* pDC, int xDest,int yDest, int cxDest, int cyDest , 
int xSrc ,int ySrc ,int cxSrc ,int cySrc); 

void Release(); 

protected: 
IPicture* m_pPic; 

OLE_XSIZE_HIMETRIC _w_him; 
OLE_YSIZE_HIMETRIC _h_him; 

CSize m_size; 

protected: 
void CalcSize(); 
}; 

#endif // define picture_h 
#endif // define PICTURE_H 

////////////////////////////////////////////////////////////////////// 
// Picture.cpp: implementation of the CPicture class. 
// Lounge Stdio 2003 
// 作者:边城浪子(QQ:16168666) 
// E-mail: krh2001.lpfdiyvbb@163.com 
////////////////////////////////////////////////////////////////////// 

#include "stdafx.h" 
#include "Picture.h" 

#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 

////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 

CPicture::CPicture() 
:m_pPic(NULL), _h_him(0), _w_him(0), m_size(0,0) 



CPicture::~CPicture() 

Release(); 


void CPicture::Release() 

if(m_pPic != NULL) 

m_pPic->Release(); 
m_pPic = NULL; 
_h_him = _w_him = 0; 
m_size.cx = m_size.cy = 0; 



BOOL CPicture::LoadPicture(LPCTSTR lpszResource, LPCTSTR lpszResType) 

Release(); 

HINSTANCE hInst = AfxFindResourceHandle(lpszResource, lpszResType); 
HRSRC hRsrc = ::FindResource(hInst, lpszResource, lpszResType); 
if(hRsrc == NULL) return FALSE; 
HGLOBAL hGlobal = LoadResource(hInst, hRsrc); 

if(hGlobal == NULL) return FALSE; 

DWORD dwSize = SizeofResource(hInst, hRsrc); 

HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, dwSize); 
if(hMem == NULL) return FALSE; 

LPVOID pSrc = ::LockResource(hGlobal); 
if(pSrc == NULL) { 
::GlobalFree(hMem); 
return FALSE; 


LPVOID pDes = ::GlobalLock(hMem); 
if(pDes == NULL){ 
//::GlobalUnlock(hGlobal); 
::GlobalFree(hMem); 
return FALSE; 


memcpy(pDes, pSrc, dwSize); 

//GlobalUnlock(hGlobal); 
GlobalUnlock(hMem); 

::FreeResource(hGlobal); 

IStream* pStm = NULL; 
CreateStreamOnHGlobal(hMem, TRUE, &pStm); 

if(!SUCCEEDED(OleLoadPicture(pStm,dwSize,TRUE,IID_IPicture,(LPVOID*)&m_pPic))) 

pStm -> Release(); 
::GlobalFree(hMem); 
pStm = NULL; 
return FALSE; 


pStm->Release(); 
::GlobalFree(hMem); 

CalcSize(); 
return TRUE; 



BOOL CPicture::LoadPictureFromFile(LPCTSTR lpszFileName) 

Release(); 

CFile file; 
if(!file.Open(lpszFileName, CFile::modeRead)) 
return FALSE; 

DWORD dwSize = file.GetLength(); 

HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, dwSize); 
if(hMem == NULL) return FALSE; 

LPVOID pDes = ::GlobalLock(hMem); 
if(pDes == NULL){ 
::GlobalFree(hMem); 
return FALSE; 


file.ReadHuge(pDes, dwSize); 

file.Close(); 

GlobalUnlock(hMem); 

IStream* pStm = NULL; 
CreateStreamOnHGlobal(hMem, TRUE, &pStm); 

if(!SUCCEEDED(OleLoadPicture(pStm,dwSize,TRUE,IID_IPicture,(LPVOID*)&m_pPic))) 

pStm -> Release(); 
::GlobalFree(hMem); 
pStm = NULL; 
return FALSE; 


pStm->Release(); 
::GlobalFree(hMem); 

CalcSize(); 
return TRUE; 



void CPicture::CalcSize() 

if(m_pPic == NULL) return; 

m_pPic->get_Width(&_w_him); 
m_pPic->get_Height(&_h_him); 

CDC* pDC = CWnd::GetDesktopWindow()->GetDC(); 
m_size.cx = _w_him; 
m_size.cy = _h_him; 

pDC->HIMETRICtoDP(&m_size); 

CWnd::GetDesktopWindow()->ReleaseDC(pDC); 



void CPicture::Draw(CDC* pDC, LPCRECT lprcDest, LPCRECT lprcSrc) 

if(m_pPic) 

CSize szOrig(lprcSrc->left, lprcSrc->top); 
CSize szSrc(lprcSrc->right - lprcSrc->left, lprcSrc->bottom - lprcSrc->top); 
pDC->DPtoHIMETRIC(&szOrig); 
pDC->DPtoHIMETRIC(&szSrc); 

m_pPic->Render(*pDC, lprcDest->left,lprcDest->top,lprcDest->right-lprcDest->left, 
lprcDest->bottom-lprcDest->top, szOrig.cx, _h_him-szOrig.cy, szSrc.cx, 
-szSrc.cy, NULL); 



void CPicture::Draw(CDC* pDC, int xDest,int yDest, int cxDest, int cyDest , 
int xSrc ,int ySrc ,int cxSrc ,int cySrc) 

Draw(pDC, CRect(xDest, yDest, xDest+cxDest, yDest+cyDest), CRect(xSrc, ySrc, xSrc+cxSrc, ySrc+cySrc)); 

}

--------------------------------------------------------------------------------------------------------------

实际上就是下面几句话就可以在指定的窗口中绘制gif,jpg和bmp图

// CImageNetView 绘制

void CImageNetView::OnDraw(CDC* /*pDC*/)

{
CImageNetDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;

m_pDC = GetDC();
DisplayImage(m_pDC->m_hDC,"E:\\Images\\rain.jpg");

}

void CImageNetView::DisplayImage(HDC hDC, LPCTSTR szImagePath)

{     
HANDLE hFile=CreateFile(szImagePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //从指定的路径szImagePath中读取文件句柄
DWORD dwFileSize=GetFileSize(hFile, NULL); //获得图片文件的大小,用来分配全局内存
HGLOBAL hImageMemory=GlobalAlloc(GMEM_MOVEABLE, dwFileSize); //给图片分配全局内存
void *pImageMemory=GlobalLock(hImageMemory); //锁定内存
DWORD dwReadedSize; //保存实际读取的文件大小
ReadFile(hFile, pImageMemory, dwFileSize, &dwReadedSize, NULL); //读取图片到全局内存当中
GlobalUnlock(hImageMemory); //解锁内存
CloseHandle(hFile); //关闭文件句柄
IStream *pIStream;//创建一个IStream接口指针,用来保存图片流
IPicture *pIPicture;//创建一个IPicture接口指针,表示图片对象
CreateStreamOnHGlobal(hImageMemory, false, &pIStream); //用全局内存初使化IStream接口指针
OleLoadPicture(pIStream, 0, false, IID_IPicture, (LPVOID*)&(pIPicture));//用OleLoadPicture获得IPicture接口指针
//得到IPicture COM接口对象后,你就可以进行获得图片信息、显示图片等操作
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
pIPicture->get_Width(&hmWidth); //用接口方法获得图片的宽和高
pIPicture->get_Height(&hmHeight);
pIPicture->Render(hDC,0,0,320,240,0,hmHeight,hmWidth,-hmHeight,NULL); //在指定的DC上绘出图片

GlobalFree(hImageMemory); //释放全局内存
pIStream->Release(); //释放pIStream
pIPicture->Release(); //释放pIPicture

}

注:似乎好像大概不能获得图像的rgb像素吧,这一点还有待确认

用API OleLoadPicture来加载JPG、GIF格式的图片(注:不支持PNG格式,另外GIF只能加载第一帧,且不支持透明)
OleLoadPicture 函数实际上创建了一个IPicture类型的COM接口对象,然后我们可以通过这个COM接口来操作图片(实际上你也可以用API OleCreatePictureIndirect来加载图片,不过相比而言OleLoadPicture函数简化了基于流的IPicture对象的创
建)

第一个参数pStream指向包含有图像数据的流的指针,第二个参数lSize为从流中读取的字节数,第三个参数fRunmode为图像属性对应的初值,第四个参数riid为涉及到的接口标识描述要返回的接口指针的类型,第五个参数ppvObj为在rrid中用到的接口指针变量的地址。

【VS开发】IPicture在指定窗口绘制图的更多相关文章

  1. 【C语言探索之旅】 第三部分第二课:SDL开发游戏之创建窗口和画布

    内容简介 1.第三部分第二课: SDL开发游戏之创建窗口和画布 2.第三部分第三课预告: SDL开发游戏之显示图像 第三部分第二课:SDL开发游戏之创建窗口和画布 在上一课中,我们对SDL这个开源库做 ...

  2. 除了创建时指定窗口位置之外,还有3种移动窗口位置的办法(移动的同时往往可以改变窗口大小)(SetWindowPos最有用,它有许多标志位)

    首先,在创立窗口对象的时候,CreateWindowEx就可以指定窗口的位置.除此之外,还有三种方法可以改变窗口的位置: procedure TWinControl.CreateWindowHandl ...

  3. VC中判断指定窗口是否被其他窗口遮挡

    本来是想判断当前窗口是否在最前面,无奈办法用尽就是不行,于是想换个思路:判断指定窗口是否被其他窗口遮挡.然后掘网三尺,找到了这个: bool CTestTray2Dlg::IsCoveredByOth ...

  4. WinAPI: GetClassName - 获取指定窗口的类名

    WinAPI: GetClassName - 获取指定窗口的类名 //声明: GetClassName( hWnd: HWND; {指定窗口句柄} lpClassName: PChar; {缓冲区} ...

  5. SDL 在指定窗口中绘图

    SDL默认会自动创建绘图窗口,可以通过设置环境变量,让其在指定窗口绘图.代码如下: [cpp] view plaincopyprint? char sdl_var[64]; sprintf(sdl_v ...

  6. JS canvas标签动态绘制图型

    使用canvas标签动态绘制图型,当点击鼠标时,以鼠标点击的坐标作为图形中心点.当点击数为偶数时画三角形,当点击数为奇数时画五角星 <!DOCTYPE HTML> <html> ...

  7. WPF编程,指定窗口图标、窗口标题,使得在运行状态下任务栏显示窗口图标的一种方法。

    原文:WPF编程,指定窗口图标.窗口标题,使得在运行状态下任务栏显示窗口图标的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_4330793 ...

  8. 用C#调用Windows API向指定窗口发送按键消息 z

    用C#调用Windows API向指定窗口发送 一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.Interop ...

  9. C# 非顶端窗口截图 - 用于查找指定窗口并截图

    原文地址:http://blog.csdn.net/u013096568/article/details/53400389 panel上可以通过DrawToBitmap截图,不管是否在屏幕外是否有遮挡 ...

随机推荐

  1. C语言定义数组时使用枚举作为数组的下标 ——c99功能

    部分参考了https://blog.csdn.net/wq3028/article/details/76204690 同时在电脑上进行验证 //温度,电磁阀传感器序号,方便数组定位 typedef e ...

  2. [SaSS] Using Object like style to create class dynamiclly

    $black: #; $white: #fff; $yellow: #ffe183; $dark-red: #e70404; $dark-green: #0d8268; $cloud-blue: #d ...

  3. js.map文件意义(转)

    什么是source map文件 source map文件是js文件压缩后,文件的变量名替换对应.变量所在位置等元信息数据文件,一般这种文件和min.js主文件放在同一个目录下. 比如压缩后原变量是ma ...

  4. SIGAI机器学习第五集 贝叶斯分类器

    讲授贝叶斯公式.朴素贝叶斯分类器.正态贝叶斯分类器的原理.实现以及实际应用 大纲: 贝叶斯公式(直接用贝叶斯公式完成分类,计算一个样本的特征向量X属于每个类c的概率,这个计算是通过贝叶斯公式来完成的. ...

  5. pandas入门之Series

    一.创建Series 参数 - Series (Series)是能够保存任何类型的数据(整数,字符串,浮点数,Python对象等)的一维标记数组.轴标签统称为索引. - data 参数 - index ...

  6. linux系统rwx(421)、777权限详解

    摘要 linux的常见权限,mark一下 常用的linux文件权限如下: 444 r--r--r-- 600 rw------- 644 rw-r--r-- 666 rw-rw-rw- 700 rwx ...

  7. OpenFOAM 中的边界条件(一)【转载】

    链接:http://xiaopingqiu.github.io/2016/04/02/Boundary-conditions-in-OpenFOAM1/ 本系列解读 OpenFOAM 中边界条件的实现 ...

  8. navicat连接远程数据库报错'client does not support authentication protocol requested by server consider ...'解决方案

    [1.cmd终端连接远程mysql数据库方法] mysql -uhello -pworld   -h192.168.1.88 -P3306 -Dmysql_oa mysql -u用户名 -p密码 -h ...

  9. Web开发中 MTV模式与MVC模式的区别 联系 概念

    MTV 与 MVC模式的区别 联系 概念: MTV: 所谓MTV指的就是: M:model (模型),指的是ORM模型. T:template (模板),一般Python都是使用模板渲染的方式来把HT ...

  10. 黑马vue---61、为什么vue组件的data要是一个函数

    黑马vue---61.为什么vue组件的data要是一个函数 一.总结 一句话总结: 因为js中以函数为变量作用域,所以这样可以保证每个组件的数据不互相影响 二.why components data ...