基于 GDI+ 的 CWtlPicture 控件






4.91/5 (16投票s)
CWtlPicture 附加到属主绘制的图片控件,并读取、显示和保存磁盘或数据库图像
引言
这是一个为 Windows Template Library (WTL) 编写的图形类,它使用 GDI+ 在属主绘制的图片(静态)控件上绘制图像。它支持位图、gif、jpeg、png 和 tif 图像格式,并允许从磁盘文件读取图像,以相同或不同的格式将图像保存到磁盘文件,读取数据库的图像或 varbinary 列,以及以相同或不同的格式写入数据库图像。
开发环境
此类与 WTL 8.0 兼容,示例是在 Visual Studio 2008 中创建的。
背景
CWtlPicture
设计用于与普通 Windows 对话框中类型设置为 Owner Draw 的通用 Picture 控件进行接口。GDI+ Bitmap 对象从磁盘或数据库加载图像数据,然后 GDI+ 图形对象在 Picture 控件表面上进行绘制。磁盘图像使用带有 Bitmap::FromFile
的 CFileDialog
打开,并使用 Bitmap::Save
和能够转换图像类型的编码器选择逻辑保存。此外,还有一个图像缩放功能和一个实现 ISequentialStream
的辅助类,用于读取和写入 OLE DB blob 数据库列。
该类还可以用于标准视图或其他窗口,通过将窗口句柄分配给 CWtlPicture,并在窗口的 OnPaint
事件处理程序中调用 Render()
函数。
使用 GDI+
GDI+ 是一个 Microsoft 图像处理库。该库及其头文件被添加到 CWtlPicture 源文件中,并在类构造函数中启动库,在析构函数中停止库。
CWtlPicture 功能
该代码可以从磁盘文件或 OLE DB 兼容的数据库打开位图、gif、jpeg、png 和 tif 图像。加载后,图像可以以支持的 5 种格式之一保存到磁盘或数据库。但是,图像处理规则适用。位图和 Jpeg 不支持透明度,因此它们不能保存为 gif、png 或 tif 透明图像,并且当图像保存为位图或 Jpeg 时会丢失透明度。此外,GDI+ 即使对于支持透明度的图像类型也不启用透明度。例如,一个不透明的 gif 图像不能通过 GDI+ 函数使其透明。
在没有数据库支持的情况下使用代码
如果您不需要数据库支持,只想处理磁盘文件,请注释掉 WtlPicture.h 中的 #define __DATABASE_SUPPORT__
行,数据库特定的代码段将被忽略。
MainDlg 的添加
您需要使用资源编辑器将一个图片控件添加到您的对话框中。为简单起见,将控件命名为 IDC_PICTURE
,并将类型设置为 Owner Draw,然后调整控件大小以满足您的需求。使用缩放属性(稍后讨论),您可以控制图像显示时的尺寸。
接下来,为 MainDlg 添加一个成员变量。例如,CWtlPicture m_odPicture;
,并在 InitDialog
中将图片控件的窗口句柄附加到它,如下所示:m_odPicture = GetDlgItem(IDC_PICTURE);
。
之后,在对话框的消息映射中设置任何所需的命令处理程序,例如文件打开和文件保存,并为绘制通知添加消息处理程序:MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
。最后,添加菜单命令和绘制的事件处理程序。绘制的代码很简单,如下所示。
// Message handler for drawing the image on the picture control LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if (IDC_PICTURE == wParam) { // Paint the background LPDRAWITEMSTRUCT lpDis = (LPDRAWITEMSTRUCT)lParam; ::GetClientRect(lpDis->hwndItem, &lpDis->rcItem); ::FillRect(lpDis->hDC, &lpDis->rcItem, (HBRUSH)(COLOR_BTNFACE + 1)); // Draw the image if (!m_odPicture.IsNull()) m_odPicture.Render(); } else bHandled = FALSE; return 0; }
添加数据库支持
要为您的项目添加数据库支持,您需要为您的数据创建一个 OLE DB 消费者类。Visual Studio Professional 或更高版本中有一个向导可以(大部分)自动完成此任务。对于 VS 的 Express 版本,您可以下载 Windows Driver Kit 7.1 来获取 ATL 功能。创建消费者类后,您需要进行一些更改以支持图像/varbinary 操作。我在之前的 OLE DB 文章中详细说明了该过程。
准备好消费者类后,为您的表添加一个成员变量(例如,CProductionProductPhoto m_dbTable;
)以及数据库操作的命令处理程序。示例项目包括移动到下一个和上一个以及数据库读/写的处理程序。
注意: MS Access 将图像存储为嵌入式 OLE 对象。SQL Server 的 Northwind 数据库具有类似的 OLE 照片对象。CWtlPicture 中的代码不读取或写入 OLE 对象。如果您需要读取 OLE 对象,可以使用类似这样的代码跳过 78 字节的 OLE 头。
void SkipOleHeader(IStream* pstm, ULONG& ulStatus) { LARGE_INTEGER liOffset = { 0, 0 }; struct OLEOBJHDR { WORD Sig; WORD Size; } Hdr; // Set stream to 0 and load header structure pstm->Seek(liOffset, STREAM_SEEK_SET, NULL); pstm->Read(&Hdr, sizeof(Hdr), NULL); // Set stream past OLE bitmap header if (Hdr.Sig == 0x1C15 && Hdr.Size == 0x2F) { liOffset.QuadPart = Hdr.Size + 1 + 30; ulStatus = DBSTATUS_S_OLE; } pstm->Seek(liOffset, STREAM_SEEK_SET, NULL); }
属性
Get/SetScaleType - 控制图像在图片控件中的显示方式。选项包括 Normal、AutoFit、Stretch 和 Zoom。AutoFit 将图像缩放到完全适合图片控件。Zoom 允许通过 render 函数设置缩放因子。小于 1.0 的缩放因子会缩小图像(例如,0.25 显示图像的 1/4 大小),大于 1.0 的因子会放大图像。
关于示例应用程序
示例对话框应用程序使用 AdventureWorks 数据库中的 Production.ProductPhoto
表。您需要访问具有这些数据库的数据库服务器才能使用示例数据库函数,或者您可以生成自己的数据库表的消费者类并将其添加到项目中。您还可能需要修改消费者类中的连接字符串以指向您的数据库。它目前设置为 localhost 并使用集成身份验证。