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

WinCE/PocketPC 快速区域创建

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (8投票s)

2007年3月24日

CPOL

4分钟阅读

viewsIcon

48407

downloadIcon

1001

一种快速创建自定义形状窗口的解决方案,使用位图蒙版。

Screenshot - cergn.jpg

引言

现代应用程序通常具有自定义的“皮肤化”外观。有许多工具、库和教程可以用于创建桌面 Windows 系统的皮肤化应用程序。不幸的是,WinCE 或 PocketPC 的情况并非如此。如果您尝试改编 Win32 程序的想法或代码,您将遇到很多挑战,就像我在创建 Skinnable Dialogs Framework 时遇到的那样。皮肤化应用程序的一个基本功能是拥有自定义形状的控件或主窗口。在 Win32 世界中创建非矩形窗口是一项相对容易的任务。您所要做的就是基于位图蒙版创建一个区域,并使用 SetWindowRgn API 为您的窗口设置它。

创建区域是创建自定义形状窗口的第一步。
我到目前为止看到的每一个区域创建器都使用了相同的想法

  • 使用位图蒙版来定义窗口的可见和透明区域
  • 在位图蒙版上调用 GetPixel 函数,以查看窗口的哪些区域应该是透明的
  • 然后调用 CreateRectRgn 基于像素或像素块创建新的矩形区域
  • 最后使用 CombineRgn 函数将这些小区域组合成最终的自定义形状区域。
但您尝试过在 PocketPC 或 WinCE 上使用这种方法吗?我尝试过,结果非常令人失望。上面的笑脸位图解析了好几分钟!
我发现,区域函数在 WinCE 上只有在您想要组合几个矩形区域时才有效。但是,当涉及到数百个小区域(就像使用位图蒙版时)时,CombineRgn 会变得慢得无法接受。
在本文中,我想介绍一种使用 ExtCreateRegion API 进行自定义区域创建的更快解决方案。该代码在 WinCE/PocketPC 和 Win32 上都能正常工作。我也用 Embedded Visual C++ 4 和 Visual Studio 2005 对其进行了测试。

解决方案

CRegionBuilder 类(请参阅文件 RegionBuilder.hRegionBuilder.cpp)只有一个公共函数 BuildRegion。它使用 ExtCreateRegion API 从手动构建的区域数据创建区域。区域数据包括一个头(RGNDATAHEADER 结构)和一个 RECT 结构数组,这些结构构成了区域。
BuildRegion 函数接受两个参数:一个已加载位图的位图句柄和一个用于存储结果区域句柄的指针。

    RegionBuilderError BuildRegion(HBITMAP hBmp, HRGN *pDest);

该函数包含结果区域中的所有非黑色像素。
可能的返回值是:rbeOKrbeNoMemrbeGDIError,如 RegionBuilder.h 中定义。如果内存分配失败,它将返回 rbeNoMem。如果任何使用的 GDI 函数返回错误,它将返回 rbeGDIError。如果一切顺利,函数将返回 rbeOK,并且结果区域句柄将被复制到目标。

一些建议

  • 在窗口可见之前,请勿对区域句柄调用 DeleteObject,而应在 OnDestroy 中释放它。
  • 在 CE 设备上绘制自定义形状窗口比绘制常规窗口慢得多,因此不要期望超高性能。
  • 如果您使用非常复杂的位图蒙版,会导致生成数千个区域 RECT(例如,640x480 的“随机噪声”),您可能会遇到设备突然崩溃或其他绘图问题。

工作原理

BuildRegion 函数首先使用 GDI GetObject 函数获取位图尺寸。为了避免缓慢的 GetPixel 函数,它直接读取位图的位。但是,除非位图是用 CreateDIBSection 创建的,否则 GetObject 函数不会返回指向位图位的指针。因此,BuildRegion 使用此函数创建一个新的单色位图,然后使用 BitBlt 将源位图复制到其中。使用单色版本的位图可以节省大量宝贵的内存。

创建单色副本后,该函数会遍历位图位以查看 RECT 数组需要多少内存。如果位图中存在水平线,它们将被打包到一个 RECT 中。

然后,该函数为矩形分配适当的内存块,并再次遍历位图以构建 RECT 数组。

它会遍历位图两次,因此只分配了所需的内存量。尽管如此,我认为它仍然相当快。比普通的 GetPixel + CombineRgn 方法快得多。

玩得开心!

© . All rights reserved.