在没有GDI ++的情况下将CLIPDATA转换为IPictureDisp [英] Convert CLIPDATA to IPictureDisp without GDI++

查看:108
本文介绍了在没有GDI ++的情况下将CLIPDATA转换为IPictureDisp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用GDI ++将CLIPDATA转换为IPictureDisp,并且在Windows应用程序中运行良好。问题是当我尝试使用来自Web服务的完全相同的代码时,会出现错误"灾难性故障(HRESULT异常:0x8000FFFF
(E_UNEXPECTED))"。


<我认为这必须是GDI ++限制。我该如何避免这个问题?


我的代码在哪里:

 // ThumbnailProvider.cpp:CThumbnailProvider $ b的实现
$ b #include" stdafx.h"
#include" ThumbnailProvider.h"


// CThumbnailProvider

/////////////////////////// ///////////////////////////////////////////////
#include< InitGuid.h>

//发明人摘要信息属性
//替换(从6.0开始)使用Microsoft Property Set。
// {3D38DE39-0588-4c14-BB37-18F4D5DD31C7}
DEFINE_GUID(FMTID_SummaryInformation_Inventor,
0x3d38de39,0x588,0x4c14,0xbb,0x37,0x18,0xf4,0xd5,0xdd,0x31,0xc7 );

#define OnErrorReturn(badsts,errorcode)if(badsts)返回errorcode;
////////////////////////////////////////////// ////////////////////////////

//帮助将png转移到位图的帮助类和函数
class Bitmap
{
public:
Bitmap();
~Bitmap();

bool IsEmpty()const;
void Clear();

void Set(HMETAFILE metaFile,int width,int height);
void Set(HBITMAP位图);

const BITMAPINFO * GetBitmapInfo()const;
void * GetBitmapData()const;

//调用者负责释放返回的对象。
HMETAFILE GetMetaFile(int& width,int& height)const;

private:
BITMAPINFO * m_gdiBitmapInfo;
void * m_gdiBitmapData;
};

Bitmap :: Bitmap():m_gdiBitmapInfo(NULL),m_gdiBitmapData(NULL)
{
}

Bitmap :: ~Ditmap()
{
Clear();
}

bool Bitmap :: IsEmpty()const
{
return!(m_gdiBitmapInfo&& m_gdiBitmapData);
}

void Bitmap :: Clear()
{
delete [] reinterpret_cast< unsigned char *>(m_gdiBitmapInfo);
delete [] static_cast< unsigned char *>(m_gdiBitmapData);
m_gdiBitmapInfo = NULL;
m_gdiBitmapData = NULL;
}

void Bitmap :: Set(HMETAFILE metaFile,int width,int height)
{
HDC screenDC = :: GetDC(NULL);
HDC memoryDC = :: CreateCompatibleDC(screenDC);
HBITMAP位图= NULL;

if(memoryDC)
{
bitmap = :: CreateCompatibleBitmap(screenDC,width,height);

if(bitmap)
{
SIZE size;
HGDIOBJ oldBitmap = :: SelectObject(memoryDC,bitmap);
int mapMode = :: SetMapMode(memoryDC,MM_ANISOTROPIC);
:: SetViewportExtEx(memoryDC,width,height,& size);
RECT rect = {0,0,width,height};

// FillSolidRect
COLORREF color = :: SetBkColor(memoryDC,RGB(255,255,255));
:: ExtTextOut(memoryDC,0,0,ETO_OPAQUE,& rect,NULL,0,NULL);
:: SetBkColor(memoryDC,color);

:: PlayMetaFile(memoryDC,metaFile);

:: SetViewportExtEx(memoryDC,size.cx,size.cy,& size);
:: SetMapMode(memoryDC,mapMode);
:: SelectObject(memoryDC,oldBitmap);
}
:: DeleteDC(memoryDC);
}

:: ReleaseDC(NULL,screenDC);

if(bitmap)
{
Set(bitmap);
:: DeleteObject(bitmap);
}
其他
清除();
}

static unsigned int BitmapInfoSize(const BITMAPINFO * gdiBitmapInfo)
{
unsigned int size = gdiBitmapInfo-> bmiHeader.biSize;
开关(gdiBitmapInfo-> bmiHeader.biBitCount)
{
案例1:
案例2:
案例4:
案例8:
size + =((unsigned int)gdiBitmapInfo-> bmiHeader.biBitCount<< 1)* sizeof(RGBQUAD);
休息;
case 24:
size + =(gdiBitmapInfo-> bmiHeader.biClrUsed?gdiBitmapInfo-> bmiHeader.biClrUsed:1)* sizeof(RGBQUAD);
休息;
case 16:
case 32:
switch(gdiBitmapInfo-> bmiHeader.biCompression)
{
case BI_BITFIELDS:
size + = 3 * sizeof (RGBQUAD); //颜色面具
休息;
case BI_RGB:
default:
size + =(gdiBitmapInfo-> bmiHeader.biClrUsed?gdiBitmapInfo-> bmiHeader.biClrUsed:1)* sizeof(RGBQUAD); // 1为NULL
break;
}
休息;
默认值:
返回0;
}
返回大小;
}

static unsigned int BitmapDataSize(const BITMAPINFO * gdiBitmapInfo)
{
unsigned int size = gdiBitmapInfo-> bmiHeader.biSizeImage;
if(!size)
{
int width = gdiBitmapInfo-> bmiHeader.biWidth;
int height = gdiBitmapInfo-> bmiHeader.biHeight;
int scanWidth = 0;
if(height< 0)
height = -height;
开关(gdiBitmapInfo-> bmiHeader.biBitCount)
{
案例1:// 16位 - 16像素
scanWidth =(宽度/ 16 +(宽度%16?1) :0))* 2; // 16位= 2个字节
break;
情况2:// 16位 - 8像素
scanWidth =(宽度/ 8 +(宽度%8?1:0))* 2; // 16位= 2个字节
break;
情况4:// 16位 - 4像素
scanWidth =(宽度/ 4 +(宽度%4?1:0))* 2; // 16位= 2个字节
break;
case 8:// 16位 - 2像素
scanWidth =(width + 1)& 〜((int)的1);
休息;
case 16:// 16位 - 1像素
scanWidth = width * 2;
休息;
情况24:// 24位 - 1像素
scanWidth =((宽* 3)+ 1)& 〜((int)的1);
休息;
case 32:// 32位 - 1像素
scanWidth = width * 4;
休息;
默认值:
返回0;
}
size =(unsigned int)scanWidth * height;
}
返回大小;
}

void Bitmap :: Set(HBITMAP hbm)
{
Clear();

HDC screenDC = :: GetDC(NULL);
BITMAPINFO bitmapInfo; memset(& bitmapInfo,0,sizeof BITMAPINFO);
bitmapInfo.bmiHeader.biSize = sizeof BITMAPINFOHEADER;
int success = :: GetDIBits(screenDC,hbm,0,0,NULL,& bitmapInfo,DIB_RGB_COLORS);

if(成功)
{
unsigned int infoSize = BitmapInfoSize(& bitmapInfo);
unsigned int dataSize = BitmapDataSize(& bitmapInfo);

m_gdiBitmapInfo = reinterpret_cast< BITMAPINFO *>(new unsigned char [infoSize]);
m_gdiBitmapData = new unsigned char [dataSize];
* m_gdiBitmapInfo = bitmapInfo;

unsigned int scanLines =(unsigned int)(bitmapInfo.bmiHeader.biHeight< 0?-bitmapInfo.bmiHeader.biHeight:bitmapInfo.bmiHeader.biHeight);
success = :: GetDIBits(screenDC,hbm,0,scanLines,m_gdiBitmapData,m_gdiBitmapInfo,DIB_RGB_COLORS);
}
:: ReleaseDC(NULL,screenDC);

if(!success)
Clear();
}

//返回的值归该对象所有。
const BITMAPINFO * Bitmap :: GetBitmapInfo()const
{
return m_gdiBitmapInfo;
}

void * Bitmap :: GetBitmapData()const
{
return m_gdiBitmapData;
}

HMETAFILE Bitmap :: GetMetaFile(int& width,int& height)const
{
if(!m_gdiBitmapInfo ||!m_gdiBitmapData)
返回NULL;

HDC dc = :: CreateMetaFile(NULL);
if(!dc)
返回NULL;

width = m_gdiBitmapInfo-> bmiHeader.biWidth;
height = m_gdiBitmapInfo-> bmiHeader.biHeight;
if(height< 0)
height = -height;

:: SetWindowOrgEx(dc,0,0,NULL);
:: SetWindowExtEx(dc,width,height,NULL);

:: StretchDIBits(dc,0,0,width,height,0,0,width,height,m_gdiBitmapData,m_gdiBitmapInfo,DIB_RGB_COLORS,SRCCOPY);

return :: CloseMetaFile(dc);
}

class GdiPlusInit
{
public:
GdiPlusInit();
~GdiPlusInit();
bool Startup(); //在任何其他GDI +调用之前需要调用此方法
void Shutdown(); //完成后使用GDI +
bool IsInitialized()const {return m_bInit; }

private:
Gdiplus :: GdiplusStartupInput * m_pGdiplusStartupInput;
ULONG_PTR m_puGdiplusToken;
UINT m_uCount;
bool m_bInit;
};

class GdiPlusInitHelper
{
public:
GdiPlusInitHelper(){init.Startup(); }
~GdiPlusInitHelper(){init.Shutdown(); }

bool IsInitialized()const {return init.IsInitialized(); }

private:
static GdiPlusInit init;
};

GdiPlusInit GdiPlusInitHelper :: init;
GdiPlusInit :: GdiPlusInit():m_puGdiplusToken(0),m_uCount(0),m_bInit(false)
{
m_pGdiplusStartupInput = new Gdiplus :: GdiplusStartupInput();
}
GdiPlusInit :: ~GdiPlusInit()
{
delete m_pGdiplusStartupInput;
m_pGdiplusStartupInput = NULL;
}
bool GdiPlusInit :: Startup()
{
if(++ m_uCount == 1)
m_bInit =(Gdiplus :: GdiplusStartup(& m_puGdiplusToken, m_pGdiplusStartupInput,NULL)== Gdiplus :: Ok);
返回m_bInit;
}

void GdiPlusInit :: Shutdown()
{
if(--m_uCount == 0&& m_bInit)
{
Gdiplus :: GdiplusShutdown(m_puGdiplusToken);
m_bInit = false;
}
}

静态bool DecodeBitmap(/ * [in] * / CLIPDATA encodeClipData,/ * [out] * / Bitmap& bitmap)
{
if(encodeClipData.cbSize< = 0)
返回false;
//创建一个临时流来读取png。
IStreamPtr tempDataStream;
HRESULT result = :: CreateStreamOnHGlobal(NULL,TRUE,& tempDataStream);
if(FAILED(result))
返回false;
const BYTE headerSize =(sizeof(DWORD)+ 4 * sizeof(WORD));
const BYTE fmtSize = sizeof(long);
//只需跳过标题信息
tempDataStream-> Write(encodeClipData.pClipData + headerSize,encodeClipData.cbSize - headerSize - fmtSize,NULL);
//初始化GDI +工具包。
GdiPlusInitHelper init;
if(!init.IsInitialized())
返回false;
Gdiplus ::位图图像(tempDataStream);
HBITMAP hBitmap;
const Gdiplus ::状态status = image.GetHBITMAP(Gdiplus :: Color :: Black,& hBitmap);
if(status!= Gdiplus :: Ok)
{
HMETAFILE hMetafile = SetMetaFileBitsEx(encodeClipData.cbSize - headerSize - fmtSize,encodeClipData.pClipData + headerSize);
if(hMetafile == NULL)
返回false;
int width =(int)(*((WORD *)(encodeClipData.pClipData + sizeof(DWORD)+ sizeof(WORD))));
int height =(int)(*((WORD *)(encodeClipData.pClipData + sizeof(DWORD)+ 2 * sizeof(WORD))));
bitmap.Set(hMetafile,width,height);
:: DeleteMetaFile(hMetafile);
} else
{
bitmap.Set(hBitmap);
:: DeleteObject(hBitmap);
}
返回true;
}

STDMETHODIMP CThumbnailProvider :: GetThumbnail(BSTR FullFileName,IPictureDisp ** ppPicture)
{
try
{
HRESULT hr = S_OK ;
LPSTORAGE pIStorage = NULL;

//获取存储空间
hr = StgOpenStorage(FullFileName,0,
STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,NULL,0,& pIStorage);
OnErrorReturn(FAILED(hr),hr);

PROPSPEC propSpec;
PROPVARIANT propVar;
IPropertySetStorage * pPropertySetStorage = NULL;
IPropertyStorage * pPropertyStorage = NULL;

//获取存储界面
hr = pIStorage-> QueryInterface(IID_IPropertySetStorage,
(void **)& pPropertySetStorage);
OnErrorReturn(FAILED(hr),hr);

//获取摘要信息
hr = pPropertySetStorage-> Open(FMTID_SummaryInformation_Inventor,
STGM_READ | STGM_SHARE_EXCLUSIVE,
& pPropertyStorage);
OnErrorReturn(FAILED(hr),hr);

propSpec.ulKind = PRSPEC_PROPID;
propSpec.propid = PIDSI_THUMBNAIL;

hr = pPropertyStorage-> ReadMultiple(1,& propSpec,& propVar);
OnErrorReturn(FAILED(hr),hr);

if(propVar.vt == VT_CF)
{
//获取剪贴板格式
CLIPDATA pClipdata = * propVar.pclipdata;
hr = GetIPictureDispFromClipdata(& pClipdata,ppPicture);
}

//删除包含在属性集存储对象中的摘要信息属性集
pPropertySetStorage->删除(FMTID_SummaryInformation_Inventor);

//减少调用接口的引用计数
pPropertySetStorage-> Release();
pIStorage-> Release();

返回S_OK;
}
catch(...)
{
// e-> Delete();
返回S_FALSE;
}
}

//从clipdata获取IPictureDisp数据
HRESULT CThumbnailProvider :: GetIPictureDispFromClipdata(CLIPDATA * pClipdata,IPictureDisp ** ppPicture)
{
OnErrorReturn(!pClipdata ||!ppPicture,E_INVALIDARG);

//确保pclipdata指向有效的clipdata对象。
OnErrorReturn(pClipdata-> pClipData == NULL || pClipdata-> cbSize == 0,E_INVALIDARG);
* ppPicture = NULL;

//从Clipdata
位图位图获取位图;
HMETAFILE hMetaFile = NULL;
if(DecodeBitmap(* pClipdata,bitmap))
{
//获取位图的维度
int cx = *(WORD *)(pClipdata-> pClipData + sizeof (DWORD)+ sizeof(WORD));
int cy = *(WORD *)(pClipdata-> pClipData + sizeof(DWORD)+ 2 * sizeof(WORD));

//将这些位转换为元文件
hMetaFile = bitmap.GetMetaFile(cx,cy);
}

PICTDESC pdesc;
pdesc.cbSizeofstruct = sizeof(pdesc);
pdesc.wmf.hmeta =(HMETAFILE)hMetaFile;
pdesc.wmf.xExt = 3200; //对应180像素
pdesc.wmf.yExt = 3200;
pdesc.picType = PICTYPE_METAFILE;

CComPtr< IPictureDisp> pPicDisp;
//当图片对象的引用计数降为零时,将销毁hematfile;
HRESULT hr = OleCreatePictureIndirect(& pdesc,IID_IPictureDisp,TRUE,(LPVOID *)& pPicDisp);
OnErrorReturn(FAILED(hr),hr);
返回pPicDisp.CopyTo(ppPicture);
}

BOOL CThumbnailProvider :: IsInvokeAllowed(DISPID / * dispid * /)
{
// TODO:在这里添加您的专用代码和/或调用基数class

返回TRUE;
}

以下是我调用代码的方法:

 private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();

dlg.Filter =" Inventor Files(* .iam; * .idw; * .ide; * .ipt; * .ipn)| * .iam; * .idw; *。ide; * .ipt; * .ipn | Assembly Fiels(* .iam)| * .iam |图形文件(* .idw)| * .idw | iFeature文件(* .ide)| * .ide |零件文件(* .ipt )| * .ipt |演示文件(* .ipn)| * .ipn |所有文件(*。*)| *。*" ;;
dlg.ShowDialog();
string ls_sourceFileName = dlg.FileName;

if(icl_thumbnailProvider == null)
icl_thumbnailProvider = new InventorThumbnailViewLib.ThumbnailProvider();
if(icl_thumbnailProvider == null)
return;

int lcl_hCode = icl_thumbnailProvider.GetHashCode();
stdole.IPictureDisp lcl_pictureThumbnail = icl_thumbnailProvider.GetThumbnail(ls_sourceFileName);

图片lcl_image = Microsoft.VisualBasic.Compatibility.VB6.Support.IPictureDispToImage(lcl_pictureThumbnail);

pictureBox1.Image = lcl_image;
}


谢谢&此致,


Rui


解决方案

怎么能我在没有GCI ++的情况下将CLIPDATA转换为IPictureDisp?




我已经有了一些使用GDI ++转换的代码,但在webservices中不支持GDI ++。




我在GDI ++中的代码如下:

 HRESULT CThumbnailProvider :: GetIPictureDispFromClipdata(CLIPDATA * pClipdata,IPictureDisp ** ppPicture)
{
OnErrorReturn(!pClipdata || !ppPicture,E_INVALIDARG);

//确保pclipdata指向有效的clipdata对象。
OnErrorReturn(pClipdata-> pClipData == NULL || pClipdata-> cbSize == 0,E_INVALIDARG);
* ppPicture = NULL;

//从Clipdata
位图位图获取位图;
HMETAFILE hMetaFile = NULL;
if(DecodeBitmap(* pClipdata,bitmap))
{
//获取位图的维度
int cx = *(WORD *)(pClipdata-> pClipData + sizeof (DWORD)+ sizeof(WORD));
int cy = *(WORD *)(pClipdata-> pClipData + sizeof(DWORD)+ 2 * sizeof(WORD));

//将这些位转换为元文件
hMetaFile = bitmap.GetMetaFile(cx,cy);
}

PICTDESC pdesc;
pdesc.cbSizeofstruct = sizeof(pdesc);
pdesc.wmf.hmeta =(HMETAFILE)hMetaFile;
pdesc.wmf.xExt = 3200; //对应180像素
pdesc.wmf.yExt = 3200;
pdesc.picType = PICTYPE_METAFILE;

CComPtr< IPictureDisp> pPicDisp;
//当图片对象的引用计数降为零时,将销毁hematfile;
HRESULT hr = OleCreatePictureIndirect(& pdesc,IID_IPictureDisp,TRUE,(LPVOID *)& pPicDisp);
OnErrorReturn(FAILED(hr),hr);
返回pPicDisp.CopyTo(ppPicture);
}


谢谢&此致,


Rui


I am using GDI++ to convert CLIPDATA to IPictureDisp and works perfect in a windows application. The problem is when I try to use exactly the same code from an webservice, that gives the error "Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))".

I think this must be a GDI++ limitation. How can I avoid this problem?

Where is my code:

// ThumbnailProvider.cpp : Implementation of CThumbnailProvider

#include "stdafx.h"
#include "ThumbnailProvider.h"


// CThumbnailProvider

//////////////////////////////////////////////////////////////////////////
#include <InitGuid.h>

// Inventor Summary Information Properties 
// Replaces (as from 6.0) use of Microsoft Property Set.
// {3D38DE39-0588-4c14-BB37-18F4D5DD31C7}
DEFINE_GUID(FMTID_SummaryInformation_Inventor, 
			0x3d38de39, 0x588, 0x4c14, 0xbb, 0x37, 0x18, 0xf4, 0xd5, 0xdd, 0x31, 0xc7);

#define OnErrorReturn(badsts, errorcode) if (badsts) return errorcode;
//////////////////////////////////////////////////////////////////////////

// Helper class and functions to help transfer png to bitmap
class Bitmap
{
public:
	Bitmap();
	~Bitmap();

	bool IsEmpty() const;
	void Clear();

	void Set(HMETAFILE metaFile, int width, int height);
	void Set(HBITMAP bitmap);

	const BITMAPINFO* GetBitmapInfo() const;
	void* GetBitmapData() const;

	// The caller is responsible for freeing the returned object.
	HMETAFILE GetMetaFile(int& width, int& height) const;

private:
	BITMAPINFO* m_gdiBitmapInfo;
	void* m_gdiBitmapData;
};

Bitmap::Bitmap() : m_gdiBitmapInfo(NULL), m_gdiBitmapData(NULL)
{
}

Bitmap::~Bitmap()
{
	Clear();
}

bool Bitmap::IsEmpty() const
{
	return !(m_gdiBitmapInfo && m_gdiBitmapData);
}

void Bitmap::Clear()
{
	delete[] reinterpret_cast<unsigned char*>(m_gdiBitmapInfo);
	delete[] static_cast<unsigned char*>(m_gdiBitmapData);
	m_gdiBitmapInfo = NULL;
	m_gdiBitmapData = NULL;
}

void Bitmap::Set(HMETAFILE metaFile, int width, int height)
{
	HDC screenDC = ::GetDC(NULL);
	HDC memoryDC = ::CreateCompatibleDC(screenDC);
	HBITMAP bitmap = NULL;

	if (memoryDC)
	{
		bitmap = ::CreateCompatibleBitmap(screenDC, width, height);

		if (bitmap)
		{
			SIZE size;
			HGDIOBJ oldBitmap = ::SelectObject(memoryDC, bitmap);
			int mapMode = ::SetMapMode(memoryDC, MM_ANISOTROPIC);
			::SetViewportExtEx(memoryDC, width, height, &size);
			RECT rect = { 0, 0, width, height };

			// FillSolidRect
			COLORREF color = ::SetBkColor(memoryDC, RGB(255, 255, 255));
			::ExtTextOut(memoryDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
			::SetBkColor(memoryDC, color);

			::PlayMetaFile(memoryDC, metaFile);

			::SetViewportExtEx(memoryDC, size.cx, size.cy, &size);
			::SetMapMode(memoryDC, mapMode);
			::SelectObject(memoryDC, oldBitmap);
		}
		::DeleteDC(memoryDC);
	}

	::ReleaseDC(NULL, screenDC);

	if (bitmap)
	{
		Set(bitmap);
		::DeleteObject(bitmap);
	}
	else
		Clear();
}

static unsigned int BitmapInfoSize(const BITMAPINFO* gdiBitmapInfo)
{
	unsigned int size = gdiBitmapInfo->bmiHeader.biSize;
	switch (gdiBitmapInfo->bmiHeader.biBitCount)
	{
	case 1:
	case 2:
	case 4:
	case 8:
		size += ((unsigned int)gdiBitmapInfo->bmiHeader.biBitCount << 1) * sizeof(RGBQUAD);
		break;
	case 24:
		size += (gdiBitmapInfo->bmiHeader.biClrUsed ? gdiBitmapInfo->bmiHeader.biClrUsed : 1) * sizeof(RGBQUAD);
		break;
	case 16:
	case 32:
		switch (gdiBitmapInfo->bmiHeader.biCompression)
		{
		case BI_BITFIELDS:
			size += 3 * sizeof(RGBQUAD); // color masks
			break;
		case BI_RGB:
		default:
			size += (gdiBitmapInfo->bmiHeader.biClrUsed ? gdiBitmapInfo->bmiHeader.biClrUsed : 1) * sizeof(RGBQUAD); // 1 for NULL
			break;
		}
		break;
	default:
		return 0;
	}
	return size;
}

static unsigned int BitmapDataSize(const BITMAPINFO* gdiBitmapInfo)
{
	unsigned int size = gdiBitmapInfo->bmiHeader.biSizeImage;
	if (!size)
	{
		int width = gdiBitmapInfo->bmiHeader.biWidth; 
		int height = gdiBitmapInfo->bmiHeader.biHeight;
		int scanWidth = 0; 
		if (height < 0)
			height = -height;
		switch (gdiBitmapInfo->bmiHeader.biBitCount)
		{
		case 1: // 16 bits - 16 pixels
			scanWidth = (width / 16 + (width % 16 ? 1 : 0)) * 2; // 16 bits = 2 bytes
			break;
		case 2: // 16 bits - 8 pixels
			scanWidth = (width / 8 + (width % 8 ? 1 : 0)) * 2; // 16 bits = 2 bytes
			break;
		case 4: // 16 bits - 4 pixels
			scanWidth = (width / 4 + (width % 4 ? 1 : 0)) * 2; // 16 bits = 2 bytes
			break;
		case 8: // 16 bits - 2 pixels
			scanWidth = (width + 1) & ~((int)1);
			break;
		case 16: // 16 bits - 1 pixel
			scanWidth = width * 2;
			break;
		case 24: // 24 bits - 1 pixel
			scanWidth = ((width * 3) + 1) & ~((int)1);
			break;
		case 32: // 32 bits - 1 pixel
			scanWidth = width * 4;
			break;
		default:
			return 0;
		}
		size = (unsigned int)scanWidth * height;
	}
	return size;
}

void Bitmap::Set(HBITMAP hbm)
{
	Clear();

	HDC screenDC = ::GetDC(NULL);
	BITMAPINFO bitmapInfo; memset(&bitmapInfo, 0, sizeof BITMAPINFO);
	bitmapInfo.bmiHeader.biSize = sizeof BITMAPINFOHEADER;
	int success = ::GetDIBits(screenDC, hbm, 0, 0, NULL, &bitmapInfo, DIB_RGB_COLORS);

	if (success)
	{
		unsigned int infoSize = BitmapInfoSize(&bitmapInfo);
		unsigned int dataSize = BitmapDataSize(&bitmapInfo);

		m_gdiBitmapInfo = reinterpret_cast<BITMAPINFO*>(new unsigned char[infoSize]);
		m_gdiBitmapData = new unsigned char[dataSize];
		*m_gdiBitmapInfo = bitmapInfo;

		unsigned int scanLines = (unsigned int)(bitmapInfo.bmiHeader.biHeight < 0 ? -bitmapInfo.bmiHeader.biHeight : bitmapInfo.bmiHeader.biHeight);
		success = ::GetDIBits(screenDC, hbm, 0, scanLines, m_gdiBitmapData, m_gdiBitmapInfo, DIB_RGB_COLORS);
	}
	::ReleaseDC(NULL, screenDC);

	if (!success)
		Clear();
}

// The returned value is owned by this object.
const BITMAPINFO* Bitmap::GetBitmapInfo() const
{
	return m_gdiBitmapInfo;
}

void* Bitmap::GetBitmapData() const
{
	return m_gdiBitmapData;
}

HMETAFILE Bitmap::GetMetaFile(int& width, int& height) const
{
	if (!m_gdiBitmapInfo || !m_gdiBitmapData)
		return NULL;

	HDC dc = ::CreateMetaFile(NULL);
	if (!dc)
		return NULL;

	width = m_gdiBitmapInfo->bmiHeader.biWidth;
	height = m_gdiBitmapInfo->bmiHeader.biHeight;
	if (height < 0)
		height = -height;

	::SetWindowOrgEx(dc, 0, 0, NULL);
	::SetWindowExtEx(dc, width, height, NULL);

	::StretchDIBits(dc, 0, 0, width, height, 0, 0, width, height, m_gdiBitmapData, m_gdiBitmapInfo, DIB_RGB_COLORS, SRCCOPY);

	return ::CloseMetaFile(dc);
}

class GdiPlusInit
{
public:
	GdiPlusInit(); 
	~GdiPlusInit();
	bool Startup();		// this method is required to be called before any other GDI+ calls
	void Shutdown();	// call this method when done using GDI+
	bool IsInitialized() const { return m_bInit; }

private:
	Gdiplus::GdiplusStartupInput* m_pGdiplusStartupInput;
	ULONG_PTR m_puGdiplusToken;
	UINT m_uCount;
	bool m_bInit;
};

class GdiPlusInitHelper
{
public:
	GdiPlusInitHelper() { init.Startup(); }
	~GdiPlusInitHelper() { init.Shutdown(); }

	bool IsInitialized() const { return init.IsInitialized(); }

private:
	static GdiPlusInit init;
};

GdiPlusInit GdiPlusInitHelper::init;
GdiPlusInit::GdiPlusInit(): m_puGdiplusToken(0), m_uCount(0), m_bInit(false) 
{
	m_pGdiplusStartupInput = new Gdiplus::GdiplusStartupInput();
}
GdiPlusInit::~GdiPlusInit()
{
	delete m_pGdiplusStartupInput;
	m_pGdiplusStartupInput = NULL;
}
bool GdiPlusInit::Startup()
{
	if (++m_uCount == 1)
		m_bInit = (Gdiplus::GdiplusStartup(&m_puGdiplusToken, m_pGdiplusStartupInput, NULL) == Gdiplus::Ok);
	return m_bInit;
}

void GdiPlusInit::Shutdown()
{
	if (--m_uCount == 0 && m_bInit)
	{
		Gdiplus::GdiplusShutdown(m_puGdiplusToken);
		m_bInit = false;
	}
}

static bool DecodeBitmap(/*[in]*/CLIPDATA encodeClipData, /*[out]*/Bitmap& bitmap)
{
	if (encodeClipData.cbSize <= 0)
		return false;			
	// Create a temporary stream to read the png from.
	IStreamPtr tempDataStream;
	HRESULT result = ::CreateStreamOnHGlobal(NULL, TRUE, &tempDataStream);
	if (FAILED(result))
		return false;		
	const BYTE headerSize = (sizeof(DWORD) + 4*sizeof(WORD));						
	const BYTE fmtSize = sizeof(long);
	//Just skip the header information
	tempDataStream->Write(encodeClipData.pClipData + headerSize, encodeClipData.cbSize - headerSize - fmtSize, NULL);				
	//Initialize GDI+ toolkits.
	GdiPlusInitHelper init;
	if (!init.IsInitialized())
		return false;						
	Gdiplus::Bitmap image(tempDataStream);
	HBITMAP hBitmap;
	const Gdiplus::Status status = image.GetHBITMAP(Gdiplus::Color::Black, &hBitmap);
	if (status != Gdiplus::Ok)
	{
		HMETAFILE hMetafile = SetMetaFileBitsEx(encodeClipData.cbSize - headerSize - fmtSize, encodeClipData.pClipData + headerSize);
		if (hMetafile == NULL)
			return false;
		int width = (int)(*((WORD*)(encodeClipData.pClipData + sizeof(DWORD) + sizeof(WORD))));
		int height = (int)(*((WORD*)(encodeClipData.pClipData + sizeof(DWORD) + 2*sizeof(WORD))));
		bitmap.Set(hMetafile,width ,height);
		::DeleteMetaFile(hMetafile);
	}else
	{
		bitmap.Set(hBitmap);
		::DeleteObject(hBitmap);	
	}			
	return true;
}

STDMETHODIMP CThumbnailProvider::GetThumbnail(BSTR FullFileName, IPictureDisp** ppPicture)
{
	try
	{
	HRESULT hr = S_OK;
	LPSTORAGE pIStorage = NULL;

	// Get the storage
	hr = StgOpenStorage (FullFileName, 0, 
		STGM_DIRECT|STGM_READ|STGM_SHARE_EXCLUSIVE, NULL, 0, &pIStorage);
	OnErrorReturn(FAILED(hr), hr);

	PROPSPEC				propSpec;
	PROPVARIANT				propVar;
	IPropertySetStorage*	pPropertySetStorage = NULL;
	IPropertyStorage*		pPropertyStorage = NULL;

	// Get the Storage interface
	hr = pIStorage->QueryInterface(IID_IPropertySetStorage, 
		(void**)&pPropertySetStorage);
	OnErrorReturn(FAILED(hr), hr);

	// Get the summary information
	hr = pPropertySetStorage->Open(FMTID_SummaryInformation_Inventor,
		STGM_READ|STGM_SHARE_EXCLUSIVE,
		&pPropertyStorage);
	OnErrorReturn(FAILED(hr), hr);

	propSpec.ulKind = PRSPEC_PROPID;
	propSpec.propid = PIDSI_THUMBNAIL;

	hr = pPropertyStorage->ReadMultiple(1, &propSpec, &propVar);
	OnErrorReturn(FAILED(hr), hr);

	if (propVar.vt == VT_CF) 
	{
		// Get clipboard format
		CLIPDATA pClipdata = *propVar.pclipdata;
		hr = GetIPictureDispFromClipdata(&pClipdata, ppPicture);
	}

	// Deletes summaray information property set contained in the property set storage object 
	pPropertySetStorage->Delete(FMTID_SummaryInformation_Inventor);

	// Decrements the reference count for the calling interfaces
	pPropertySetStorage->Release();
	pIStorage->Release();

	return S_OK;
	}
	catch(...)
		{
		//e->Delete();
		return S_FALSE;
		}
}

// Get IPictureDisp data from clipdata
HRESULT CThumbnailProvider::GetIPictureDispFromClipdata(CLIPDATA* pClipdata, IPictureDisp** ppPicture)
{
	OnErrorReturn(!pClipdata || !ppPicture, E_INVALIDARG);

	//make sure pclipdata points to a valid clipdata object.
	OnErrorReturn(pClipdata->pClipData == NULL || pClipdata->cbSize == 0, E_INVALIDARG);
	*ppPicture = NULL;

	//Get the bitmap from the Clipdata
	Bitmap bitmap;
	HMETAFILE hMetaFile = NULL;
	if(DecodeBitmap(*pClipdata, bitmap))
	{
		//Get the dimension of bitmap
		int cx = *(WORD*)(pClipdata->pClipData + sizeof(DWORD) + sizeof(WORD));
		int cy = *(WORD*)(pClipdata->pClipData + sizeof(DWORD) + 2*sizeof(WORD));	

		//Turn the bits into a metafile
		hMetaFile = bitmap.GetMetaFile(cx, cy);
	}

	PICTDESC pdesc;
	pdesc.cbSizeofstruct = sizeof(pdesc);
	pdesc.wmf.hmeta  = (HMETAFILE)hMetaFile;
	pdesc.wmf.xExt = 3200;	// corresponds to 180 pixels
	pdesc.wmf.yExt = 3200;
	pdesc.picType = PICTYPE_METAFILE;

	CComPtr<IPictureDisp> pPicDisp;
	//The hematfile will be destroyed when the picture object's ref count drops to zero;
	HRESULT hr = OleCreatePictureIndirect(&pdesc, IID_IPictureDisp, TRUE, (LPVOID*)& pPicDisp);	
	OnErrorReturn(FAILED(hr), hr);
	return pPicDisp.CopyTo(ppPicture);
}

BOOL CThumbnailProvider::IsInvokeAllowed(DISPID /*dispid*/)
{
	// TODO: Add your specialized code here and/or call the base class

	return TRUE;
}

Here is how I call the code:

private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            dlg.Filter = "Inventor Files (*.iam; *.idw; *.ide; *.ipt; *.ipn)|*.iam;*.idw;*.ide;*.ipt;*.ipn|Assembly Fiels (*.iam)|*.iam|Drawing Files (*.idw)|*.idw|iFeature Files (*.ide)|*.ide|Part Files (*.ipt)|*.ipt|Presentation Files (*.ipn)|*.ipn|All Files (*.*)|*.*";
            dlg.ShowDialog();
            string ls_sourceFileName = dlg.FileName;

            if (icl_thumbnailProvider == null)
                icl_thumbnailProvider = new InventorThumbnailViewLib.ThumbnailProvider();
            if (icl_thumbnailProvider == null)
                return;

            int lcl_hCode = icl_thumbnailProvider.GetHashCode();
            stdole.IPictureDisp lcl_pictureThumbnail = icl_thumbnailProvider.GetThumbnail(ls_sourceFileName);

            Image lcl_image = Microsoft.VisualBasic.Compatibility.VB6.Support.IPictureDispToImage(lcl_pictureThumbnail);

            pictureBox1.Image = lcl_image;
        }

Thanks & Regards,

Rui

解决方案

How can I convert CLIPDATA to IPictureDisp without GCI++?

I already have some code to convert using GDI++ but in webservices GDI++ is not supported.

The code I have in GDI++ is the following:

HRESULT CThumbnailProvider::GetIPictureDispFromClipdata(CLIPDATA* pClipdata, IPictureDisp** ppPicture)
{
	OnErrorReturn(!pClipdata || !ppPicture, E_INVALIDARG);

	//make sure pclipdata points to a valid clipdata object.
	OnErrorReturn(pClipdata->pClipData == NULL || pClipdata->cbSize == 0, E_INVALIDARG);
	*ppPicture = NULL;

	//Get the bitmap from the Clipdata
	Bitmap bitmap;
	HMETAFILE hMetaFile = NULL;
	if(DecodeBitmap(*pClipdata, bitmap))
	{
		//Get the dimension of bitmap
		int cx = *(WORD*)(pClipdata->pClipData + sizeof(DWORD) + sizeof(WORD));
		int cy = *(WORD*)(pClipdata->pClipData + sizeof(DWORD) + 2*sizeof(WORD));	

		//Turn the bits into a metafile
		hMetaFile = bitmap.GetMetaFile(cx, cy);
	}

	PICTDESC pdesc;
	pdesc.cbSizeofstruct = sizeof(pdesc);
	pdesc.wmf.hmeta  = (HMETAFILE)hMetaFile;
	pdesc.wmf.xExt = 3200;	// corresponds to 180 pixels
	pdesc.wmf.yExt = 3200;
	pdesc.picType = PICTYPE_METAFILE;

	CComPtr<IPictureDisp> pPicDisp;
	//The hematfile will be destroyed when the picture object's ref count drops to zero;
	HRESULT hr = OleCreatePictureIndirect(&pdesc, IID_IPictureDisp, TRUE, (LPVOID*)& pPicDisp);	
	OnErrorReturn(FAILED(hr), hr);
	return pPicDisp.CopyTo(ppPicture);
}

Thanks & Regards,

Rui


这篇关于在没有GDI ++的情况下将CLIPDATA转换为IPictureDisp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆