65.9K
CodeProject 正在变化。 阅读更多。
Home

WTL IPicture Viewer:WTL BmpView 样本应用程序的更新

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (5投票s)

2011年6月29日

CPOL

5分钟阅读

viewsIcon

23618

downloadIcon

1049

WTL BmpView 样本应用程序的更新版本,使用 OLE Picture 对象处理多种图像类型。

WTLIPicture Viewer Application

引言

本文介绍了 WTLIPicture Viewer,它是 WTL BmpView 示例应用程序的更新版本。WTLIPicture Viewer 使用 OLE Picture 对象的包装器,并支持多种图像类型,包括位图、光标、增强图元文件、图标、gif、jpeg 和 windows 图元文件。可以打开和缩放图像文件,从剪贴板复制或粘贴图像,以及预览和打印图像。

Picture 对象包装器包含在源文件 WTLIPicture.h 中,并提供了将 Picture 对象与像示例 WTLIPicture Viewer 这样的图像查看器一起使用所需的所有代码。它包含 MFC 中 CPictureHolder 类的 WTL 移植和扩展,还包含支持多种剪贴板图像格式的类。此外,它还为大多数支持的图像格式提供了一组半标准的结构,类似于 BITMAPFILEHEADER BITMAPINFOHEADER

关于 PNG 的说明

WTLIPicture Viewer 不支持 PNG 图像,因为 IPicture 的出现早于 PNG。

Picture 对象

OLE Picture 对象为位图、图标和图元文件提供了语言无关的抽象。主要接口是 IPicture IPictureDispIPicture 接口允许调用者管理图片属性并在图形渲染中使用图片。IPictureDisp 接口派生自 IDispatch ,以便通过自动化访问图片的属性。

以下小节将解释 CPixT 模板提供的各种方法,以简化 Picture 对象的使用。成员变量 m_pPix 是一个 IPicture 指针。

创建方法

CreateEmpty()CPixT 提供的用于初始化 Picture 对象的基本方法。所有其他 create 方法都调用它,并将指向已填写的 PICTDESC 结构(包含图片信息)的指针传递进去。

BOOL CreateEmpty(LPPICTDESC lpPictDesc = NULL, BOOL bOwn = FALSE)
{ // build the PICTDESC structure if not passed in
  if (lpPictDesc == NULL)
  {
    PICTDESC pdesc;
    pdesc.cbSizeofstruct = sizeof(pdesc);
    pdesc.picType = PICTYPE_NONE;
    lpPictDesc = &pdesc;
  }

  // create the IPicture object
  return SUCCEEDED(::OleCreatePictureIndirect(lpPictDesc, IID_IPicture, bOwn,
		   (LPVOID*)&m_pPix)); }

CreateFromBitmap() 是一组三个方法,允许从位图资源、CBitmap 指针或位图句柄初始化 Picture 对象。以下代码显示了接受位图句柄、可选调色板以及一个指示是否将位图所有权转移给 Picture 对象的标志的版本。

BOOL CreateFromBitmap(HBITMAP hbm, HPALETTE hpal, BOOL bTransferOwnership)
{ PICTDESC pdesc;
  pdesc.cbSizeofstruct = sizeof(pdesc);
  pdesc.picType = PICTYPE_BITMAP;
  pdesc.bmp.hbitmap = hbm;
  pdesc.bmp.hpal = hpal;

  return CreateEmpty(&pdesc, bTransferOwnership); }

CreateFromEnhancedMetafile() 支持从增强图元文件创建 Picture 对象。

CreateFromIcon() 提供的方法可以从图标资源或图标句柄创建 Picture 对象。它支持图标和光标图像。

CreateFromMetafile() 支持从 Windows 图元文件初始化 Picture 对象。

加载方法

这些方法提供了从文件和流等各种输入源加载 Picture 对象的机制。

LoadFromDispatch 从图像文件加载 Picture 对象并设置 IPictureDisp 接口。

BOOL LoadFromDispatch(LPTSTR szFilePath)
{ // create a variant for the file name
  VARIANT varFileName;
  varFileName.vt = VT_BSTR;
  varFileName.bstrVal = CComBSTR(szFilePath);

  LPDISPATCH lpDisp = NULL;

  // load the picture object from the file
  BOOL bResult = SUCCEEDED(::OleLoadPictureFile(varFileName, &lpDisp));

  // initialize the dispatch interface
  if (bResult) lpDisp->QueryInterface(IID_IPicture, (LPVOID*)&m_pPix);

  return bResult; }

LoadFromFile() 使用标准文件 I/O 从图像文件加载 Picture 对象。

LoadFromIStream()IStream 加载。

LoadFromISequentialStream() 使用 ISequentialStream 指针加载 Picture 对象,例如来自 OLE DB 提供程序的指针。

LoadFromPath() 从文件名或 URL 加载。这是加载图像的最简单方法,但据说会泄漏资源。

BOOL LoadFromPath(LPCTSTR szFilePath)
{ return SUCCEEDED(::OleLoadPicturePath(CComBSTR(szFilePath), NULL, 0, 0,
		   IID_IPicture, (LPVOID *)&m_pPix)); }

保存方法

这些方法提供了将 Picture 对象保存到文件的机制。

SaveToDispatch() 使用 IPictureDisp 接口将 Picture 对象保存到图像文件。

BOOL SaveToDispatch(LPTSTR szFilePath)
{ BOOL bResult = FALSE;
  LPPICTUREDISP pDisp = NULL;

  if (SUCCEEDED(m_pPix->QueryInterface(IID_IPictureDisp, (LPVOID*)&pDisp)))
    BOOL bResult = SUCCEEDED(::OleSavePictureFile((LPDISPATCH)pDisp,
			     CComBSTR(szFilePath)));

  return bResult; }

SaveToFile() 使用标准文件 I/O 将 Picture 对象保存到图像文件。

渲染方法

将已创建或加载到 IPicture 中的图像绘制到设备上下文中。您可以传入一个小于图像尺寸的矩形以缩小,或传入一个大于图像尺寸的矩形以放大。

void Render(CDCHandle dc, const CRect& rcRender)
{ long hmWidth;
  long hmHeight;

  m_pPix->get_Width(&hmWidth);
  m_pPix->get_Height(&hmHeight);

  m_pPix->Render(dc, rcRender.left, rcRender.top, rcRender.Width(),
		 rcRender.Height(), 0, hmHeight-1, hmWidth, -hmHeight, NULL); }

属性

  1. GetAttributes() - 返回一个包含透明度和可缩放性标志的 DWORD
  2. GetDescription() - 返回图像类型的文本描述
  3. GetHandle() - 返回图像的 OLE_HANDLE
  4. GetHandle() - 接收一个 OLE_HANDLE 的引用并设置其值
  5. GetPixInformation() - 返回一个包含图像信息(如大小、类型以及图像的前 256 字节)的结构
  6. GetSizeInHiMetric() - 接收一个 SIZE 引用并以 HiMetric 返回高度和宽度
  7. GetSizeInPixels() - 同上,但以 Pixels 为单位
  8. GetType() - 返回数字图像类型,例如 PICTYPE_BITMAP

测试

这些方法返回一个 BOOL 值,指示 IPicture 包含的图像类型。

  1. IsNull() - m_pPixnull
  2. IsBitmap() - 图像是位图、GIF 或 JPEG
  3. IsMetafile() - 图像是 Windows 图元文件
  4. IsIcon() - 图像是图标或光标
  5. IsEnhMetafile() - 图像是增强图元文件

剪贴板助手类

WTLIPicture.h 包含两个类,用于获取或设置剪贴板图像。CClipboardFormatDlg 是一个小型对话框,当剪贴板上有多种图像类型可用时,用于提示选择图像类型。它支持位图、增强图元文件和 Windows 图元文件。CWTLIPictureClipboard 为位图、图标(转换为位图)以及两种图元文件类型提供 **复制** 功能。它还为位图和两种类型的图元文件提供 **粘贴** 功能。

半标准结构

WTLIPicture.h 提供了一组半标准的结构,类似于 BITMAPFILEHEADERBITMAPINFOHEADER。为光标和图标、jpeg、增强和 Windows 图元文件提供了结构。这些结构的目的是提供对图像文件头中常用引用值的访问。例如,这是 Windows 图元文件的 METAFILEHEADER 定义。

//////////////////////////////////////////////////////////
/* METAFILEHEADER (22 bytes) placeable metafile header. */
/* Metafiles may also start with a METAINFOHEADER only	*/
/* or with a METAFILEPICT clipboard header (see below)	*/
//////////////////////////////////////////////////////////
#include < pshpack2.h >
typedef struct tagMETAFILEHEADER {
  DWORD mfKey;	    // Magic number (always 0x9AC6CDD7)
  WORD mfHandle;    // Metafile HANDLE number (always 0)
  WORD mfLeft;	    // Left coordinate in metafile units (twips)
  WORD mfTop;	    // Top coordinate in metafile units
  WORD mfRight;     // Right coordinate in metafile units
  WORD mfBottom;    // Bottom coordinate in metafile units
  WORD mfInch;	    // Number of metafile units per inch.
		    // Unscaled = 1440; 720 = 2:1; 2880 = 1:2; etc.
  DWORD mfReserved; // Reserved (always 0)
  WORD mfChecksum;  // Checksum value for previous 10 WORDs
} METAFILEHEADER, FAR *LPMETAFILEHEADER;
#include < poppack.h >

包含文件 pshpack2.hpoppack.h 是必需的,以便对结构进行字节对齐,因为它不以四字节边界结束。

已知问题

  1. 不支持 PNG 图像,因为 IPicture 不支持 PNG
  2. 复制到剪贴板并以 WMF 格式粘贴回的 EMF 图像未对齐
  3. SaveToDispatch() 可能会导致系统崩溃,尤其是在处理大型图像(> 5 MB)时
  4. 缩放图像滚动时可能会出现轻微闪烁

致谢

CWTLIPictureT 模板类是 Microsoft Foundation Class 库中 CPictureHolder 的 WTL 移植和扩展。WTLIPictureViewer 应用程序基于 Windows Template Library 随附的 BmpView 示例应用程序。

使用条款

本文提供的示例应用程序是免费的,但受限于原始 BmpView 示例应用程序和 CPictureHolder 的任何限制。WTLIPicture.h 中提供的源代码可免费用于任何目的,前提是遵守 CPOL 要求。

本软件按“现状”分发,不提供任何形式的担保。

© . All rights reserved.