适用于 Win32 和 WinCE 的 DIBSection 包装器






4.87/5 (25投票s)
一个类,使使用 DIBSections 就像使用 CBitmap 一样简单。
前言
示例演示工作区包含两个项目:用于 Win32 环境的 DIBSectionTest 和用于 CE 环境的 DIBSectionTestCE,它们演示了 DIBSection
包装器。您需要在构建 DIBSectionTestCE.dsw 之前安装 Microsoft 的 CE SDK。此外,Kenny Goers 还移植了一个 DIBSection 版本,它不依赖于 MFC。此版本目前与 MFC 版本略有不同步,仅为方便起见提供。
引言
设备无关位图 (DIB) 提供了一种以独立于计算机当前显示设置的方式来操作和显示位图的方法。它们也是标准 Windows .BMP 文件的格式,因此拥有一种加载、显示和修改 DIB 的方法非常有用。
Win32 提供了许多不同的方法来处理 DIB,包括标准的 DIB 函数,如 SetDIBitsToDevice
、GetDIBits
等,DrawDib
函数,以及 GDI 函数,如用于 DIBSections 的 BitBlt
。
然而,在 CE 环境中工作时,许多我们熟悉且喜爱的常规函数已被舍弃,以减小操作系统整体尺寸。因此,我们只剩下使用 DDB(通过 CBitmap
)或 DIBSections 的可能性。但这并非巨大的障碍,因为 DIBSections 在某种程度上优于普通 DIB,它们拥有一个关联的 HBITMAP
句柄,因此可以通过 GDI 函数(如 BitBlt
和 StretchBlt
)进行操作。此外,DIBSection 的句柄可以被选择到内存 DC 中,然后使用 TextOut
、Line
等 GDI 函数直接绘制。这比手动访问 DIB 的位并逐像素绘制要容易得多。
从 MFC 程序员的角度来看,DIBSections 唯一的问题是没有 DIBSection 包装器。Jeff Prosise 在其著作《Programming Windows 95 with MFC》中讨论了 DIBSections 及其优点,但指出由于下一版 MFC 将包含一个 DIBSection 包装器类,因此他在书中提供它是没有意义的。糟糕!自该书出版以来,MFC 已经更新了好几个版本,但仍然没有 DIBSection 包装器类的迹象。
随着 CE 的出现,DIBSections 变得更加重要。在此,我提出 CDIBSectionLite
类 - 这是一个适用于 Win32 和 WinCE 平台的 DIBSection 包装器类。该类提供了一个简单的 DIBSections 接口,包括加载、保存和显示 DIBSections。Win32 和 CE 2.11 及以上版本提供完整的调色板支持。
请注意,CE 引入了一种新的位深度,即每像素 2 位。这适用于较旧的 4 级灰度设备。CDIBSectionLite
仅在 CE 构建中支持此像素深度。
创建和显示 DIBSections
创建 DIBSection 的第一步是填充 BITMAPINFOHEADER
结构。如果您是从头开始创建 DIBSection,只需随意填写这些值即可。另一方面,如果您想将 DDB 转换为 DIBSection,那么您最好的朋友是 GetDIBits 函数。它通过查询提供的位图的值来为您填充 BITMAPINFOHEADER
结构。
不幸的是,CE 不支持此函数,因此您必须自己完成。虽然这不是什么大问题,但它确实使得从提供的位图中获取颜色表信息变得稍微困难一些。Microsoft 在 KB 文章《HOWTO: Get the Color Table of a DIBSection in Windows CE》中提供了一些有用的帮助。KB 文章中代码的一个限制是它只提取本身就是 DIBSections 的位图的颜色表信息。CDIBSectionLite
通过为没有颜色表信息的 DDB 合成一个半调色板来解决这个问题。
一旦您填充了 BITMAPINFOHEADER
结构,包括颜色表条目,只需调用 CreateDIBSection
。此函数将返回一个 HBITMAP
句柄以及一个指向实际图像位的指针。您还能要求什么呢!
要实际显示 DIBSections,只需使用经过验证的 Windows GDI 函数(BitBlt 等)。在 CE 中,某些功能会丢失,例如 GDIFlush 和 SetStretchBltMode,但总的来说,作为 DIBSection 创建的 HBITMAP 与从 DDB 创建的 HBITMAP 的使用方式没有区别。
CDIBSectionLite
类支持 DrawDib 函数。这些函数提供高速显示和抖动处理,但不幸的是在 CE 上不可用。要切换使用 Windows GDI 和 DrawDib 例程,请使用 CDIBSectionLite::SetDither(...)
函数。
使用 CDIBSectionLite
此类非常简单易用,可以隐藏所有繁琐的细节。可以使用 SetBitmap()
(接受设备相关位图、设备无关位图或资源 ID)或使用 Load()
(允许从磁盘加载图像)来设置位图。要显示位图,只需使用 Draw 或 Stretch。
例如:
CDIBsectionLite dibsection; dibsection.Load(_T("image.bmp")); dibsection.Draw(pDC, CPoint(0,0)); // pDC is of type CDC* CDIBsectionLite dibsection; dibsection.SetBitmap(IDB_BITMAP); dibsection.Draw(pDC, CPoint(0,0)); // pDC is of type CDC*
CDIBsectionLite API
CDIBSectionLite
API 包括用于加载和显示图像的方法、用于提取图像信息的函数以及用于获取和设置当前调色板的调色板选项。请注意,调色板方法仅在 Win32 或 CE 2.11 及更高版本中可用。
// Attributes HBITMAP GetSafeHandle() const // Gets a HBITMAP handle to the image operator HBITMAP() const // Gets a HBITMAP handle to the image CSize GetSize() const // Gets the size of the image in pixels int GetHeight() const // Gets the height of the image in pixels int GetWidth() const // Gets the width of the image in pixels int GetPlanes() const // Gets the number of colour planes in the image int GetBitCount() const // Gets the bits per pixel for the image LPVOID GetDIBits() // Returns a pointer to the image bits LPBITMAPINFO GetBitmapInfo() // Returns a pointer a BITMAPINFO structure for the image DWORD GetImageSize() const // Returns the size of the image (in bytes) LPBITMAPINFOHEADER GetBitmapInfoHeader() // Returns a pointer to a BITMAPINFOHEADER structure LPRGBQUAD GetColorTable() // Returns a pointer to the RGBQUAD data in the DIB color table // Operations (Palette) LPRGBQUAD GetColorTable() BOOL SetColorTable(UINT nNumColors, RGBQUAD *pColors); int GetColorTableSize() // these only available if DIBSECTION_NO_PALETTE not defined CPalette *GetPalette(); BOOL SetPalette(CPalette* pPalette); BOOL SetLogPalette(LOGPALETTE* pLogPalette); // Operations (Bitmap) // Loads an image into the object. // nIDResource - Bitmap resource ID // lpszResourceName - Bitmap resource ID // hBitmap - existing image handle // palette - palette to be used for image construction (Win32 or CE 2.11 only) // lpBitmapInfo - pointer to BITMAPINFO structure // lpBits - pointer to image bits BOOL SetBitmap(UINT nIDResource); BOOL SetBitmap(LPCTSTR lpszResourceName); BOOL SetBitmap(HBITMAP hBitmap, CPalette* pPalette = NULL); BOOL SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits); BOOL Load(LPCTSTR lpszFileName); // Load form disk BOOL Save(LPCTSTR lpszFileName); // Save to disk BOOL Copy(CDIBSectionLite& Bitmap); // make a copy // Operations (Display) BOOL Draw(CDC* pDC, CPoint ptDest, BOOL bForceBackground = FALSE); BOOL Stretch(CDC* pDC, CPoint ptDest, CSize size, BOOL bForceBackground = FALSE); // Only available in Win32 BOOL SetDither(BOOL bDither); // Set whether or not dithering is on BOOL GetDither(); void DeleteObject() // Deletes the image and frees all memory
最新更新
- 2000 年 5 月 4 日 - 该类已根据 3DFX 的 Jim Miller 的更正进行了更新,以修复压缩位图的错误。
- 2000 年 9 月 20 日 - 修复了 Save() 中的错误(保存时多出 4 个字节 - Tadeusz Dracz)
允许 SetBitmap 中的 lpBits 为 NULL - Don Grasberger
修复了 NumColorEntries 错误 - Itay Szekely
修复了 Load() 中的缓冲区溢出错误 - Itay Szekely
- 2001 年 4 月 5 日 - 修复了 PocketPC 的 16/32 bpp 位图问题(Dan Robbins)
非 MFC 移植(Kenny Goers) - 2001 年 5 月 22 日 - 修复了 NumColorEntries 的 24bpp 情况中缺失的 break(Steve Kramp)