在没有GDI ++的情况下将CLIPDATA转换为IPictureDisp [英] Convert CLIPDATA to IPictureDisp without GDI++
问题描述
我正在使用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屋!