WIN32 区域指南





5.00/5 (37投票s)
关于如何使用 WIN32 SDK 创建和使用区域的指南
引言
区域是 Windows 中的一种非常实用的资源。它们是设备无关的,这意味着在创建或使用区域时不需要设备上下文 (DC)。但是,WIN32 GDI 中有许多函数需要使用区域。
区域的一些有用之处包括:
- 更新区域,绘制
- 剪裁,绘制
- 命中检测
- 定义窗口形状,不规则形状的窗口
许多与区域相关的函数都非常简单,几乎不需要解释。事实上,MSDN 的定义已经足够解释这些函数了。然而,有些函数会稍微难理解和掌握一些,因此我们添加了额外的细节来解释这些函数。解释中可能还会附带一些图示。
区域创建
有多种方法可以创建区域。可以使用许多函数来创建区域,从简单的形状(如矩形或椭圆)到复杂的形状(如文本字符串的轮廓)。下面列出了描述每个创建函数的表格。
函数 | 描述 |
CreateEllipticRgn | 创建椭圆区域。与绘制椭圆一样,椭圆区域非常大,如果使用大量椭圆区域,可能会减慢程序速度。 |
CreateEllipticRgnIndirect | 从 RECT 结构创建椭圆区域。与绘制椭圆一样,椭圆区域非常大,如果使用大量椭圆区域,可能会减慢程序速度。 |
CreatePolygonRgn | 创建多边形区域。 |
CreatePolyPolygonRgn | 创建由一系列多边形组成的区域。 |
CreateRectRgn | 创建矩形区域。 |
CreateRectRgnIndirect | 从 RECT 结构创建矩形区域。 |
CreateRoundRectRgn | 创建带有圆角的矩形区域。 |
ExtCreateRegion | 根据指定的区域和变换数据创建区域。 |
PathToRegion | 从 DC 中创建的 WIN32 路径创建区域。 |
操作
可以对区域执行一些操作,以便查询、修改或测试其数据。
CombineRgn
创建了一些基本区域后,可以使用布尔运算来创建更复杂的区域,方法是使用 CombineRgn
。此函数有五种可以用来组合两个不同区域的操作。下面是 CombineRgn
中可以执行的每种布尔运算的示例。
值 | 描述 | 结果 |
RGN_AND | 创建两个组合区域的交集。CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_AND);
| ![]() |
RGN_COPY | 创建 hrgnSrc1 指定区域的副本。CombineRgn(hrgnDest, hrgnSrc1, NULL, RGN_COPY);
| 无图片 |
RGN_DIFF | 组合 hrgnSrc1 中不属于 hrgnSrc2 的部分。CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_DIFF);
| ![]() ![]() |
RGN_OR | 创建两个组合区域的并集。CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_OR);
| ![]() |
RGN_XOR | 创建两个组合区域的并集,但不包括任何重叠区域。CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_XOR);
| ![]() |
还有一点需要指出的是,CombineRgn
中的目标区域可以是源区域之一。因此,如果您通过添加或减去另一个区域来不断修改一个区域,您可以执行一次组合操作,而不必担心复制调整后的区域。这里有一个示例。
HRGN hCacheRgn;
HRGN hUpdateRgn;
...
//C: Convoluted way.
//C: Initialize a temporary region.
HRGN hTemp = ::CreateRectRgn(0,0,0,0);
//C: Subtract the update region from the Cache region.
::CombineRgn(hTemp, hCacheRgn, hUpdateRgn, RGN_DIFF);
//C: Copy the Temp region back into the Cache region.
::CombineRgn(hCacheRgn, hTemp, NULL, RGN_COPY);
//C: Destroy the Temp region.
::DeleteObject(hTemp);
//C: Simple way
::CombineRgn(hCacheRgn, hCacheRgn, hUpdateRgn, RGN_DIFF);
EqualRgn
EqualRgn
函数检查指定的两个区域,以确定它们是否相同。如果两个区域的大小和形状相等,则认为它们相同。
BOOL EqualRgn(
HRGN hSrcRgn1, // handle to first region
HRGN hSrcRgn2 // handle to second region
);
PtInRegion
PtInRegion
函数确定指定点是否位于指定区域内。此函数对于在控件上创建命中测试区域非常有用。例如,一个带有用户可以单击的热区的位图。
BOOL PtInRegion(
HRGN hrgn, // handle to region
int X, // x-coordinate of point
int Y // y-coordinate of point
);
RectInRegion
RectInRegion
函数与 PtInRegion
非常相似,但它会确定指定矩形的任何部分是否位于区域边界内。
BOOL RectInRegion(
HRGN hrgn, // handle to region
CONST RECT *lprc // pointer to rectangle
);
GetRgnBox
GetRgnBox
函数检索指定区域的边界矩形。
int GetRgnBox(
HRGN hrgn, // handle to a region
LPRECT lprc // bounding rectangle
);
OffsetRgn
OffsetRgn
函数按指定的偏移量移动区域。
int OffsetRgn(
HRGN hrgn, // handle to region
int nXOffset, // offset along x-axis
int nYOffset // offset along y-axis
);
SetRectRgn
SetRectRgn
函数将区域转换为具有指定坐标的矩形区域。
BOOL SetRectRgn(
HRGN hrgn, // handle to region
int nLeftRect, // x-coordinate of upper-left corner of rectangle
int nTopRect, // y-coordinate of upper-left corner of rectangle
int nRightRect, // x-coordinate of lower-right corner of rectangle
int nBottomRect // y-coordinate of lower-right corner of rectangle
);
绘制函数
WIN32 提供了一些函数,允许使用区域句柄来实现绘制效果。这些效果包括使用画笔填充、描边和反转当前内容。
FillRgn
FillRgn
函数使用指定的画笔填充区域。
BOOL FillRgn(
HDC hdc, // handle to device context
HRGN hrgn, // handle to region to be filled
HBRUSH hbr // handle to brush used to fill the region
);
FrameRgn
FrameRgn
函数使用指定的画笔绘制指定区域的边框。
BOOL FrameRgn(
HDC hdc, // handle to device context
HRGN hrgn, // handle to region to be framed
HBRUSH hbr, // handle to brush used to draw border
int nWidth, // width of region frame
int nHeight // height of region frame
);
InvertRgn
InvertRgn
函数反转指定区域中的颜色。
BOOL InvertRgn(
HDC hdc, // handle to device context
HRGN hrgn // handle to region to be inverted
);
PaintRgn
PaintRgn
函数类似于 FillRgn
函数,但该函数使用当前选择到设备上下文中的画笔来绘制指定的区域。
BOOL PaintRgn(
HDC hdc, // handle to device context
HRGN hrgn // handle to region to be painted
);
GetRegionData
GetRegionData
函数使用数据填充指定的缓冲区...
DWORD GetRegionData(
HRGN hRgn, // handle to region
DWORD dwCount, // size of region data buffering a region.
This data includes the dimensions of the rectangles that make up the region.
LPRGNDATA lpRgnData // region data buffer
);
区域数据
WIN32 区域实际上是一组在一个对象中管理的矩形。RGN_DATA
结构管理着这组矩形以及维护区域所需的其他一些数据。可以通过 GetRegionData
函数访问 RGN_DATA
结构。可以使用 ExtCreateRgn
函数使用 RGN_DATA
结构创建一个区域对象。下图显示了 HRGN
对象的内部表示。区域中的每个矩形都使用交替颜色的画笔进行绘制。
ExtCreateRgn
ExtCreateRegion
函数根据指定的区域和变换数据创建区域。
HRGN ExtCreateRegion(
CONST XFORM *lpXform, // transformation data
DWORD nCount, // size of region data
CONST RGNDATA *lpRgnData // region data buffer
);
需要注意的是,Windows 2000 可以接受包含重叠矩形的区域。如果您尝试在 Windows NT4 上使用包含重叠矩形的数据创建区域,此函数将失败。因此,如果您在 Windows 2000 计算机上创建了一个这样的区域,并将区域的 RGN_DATA
存储在文件中,或者将数据通过网络发送到 Windows NT4 计算机,当您尝试在结构上调用 ExtCreateRgn
时,它将失败。
Windows 9x 内核不支持涉及剪切或旋转的世界变换。如果变换 (XFORM
) 矩阵对区域进行了缩放或平移,ExtCreateRegion
将失败。
演示
创建的程序旨在演示区域的一些可能性,它是一个交互式窗口,允许用户创建两个区域。用户可以使用矩形、椭圆或圆角矩形工具向任一源区域添加新部分。多边形工具被省略了,仅仅是因为将该工具集成到 UI 中需要额外的繁琐工作,但使用多边形是完全可能的。
以下是创建源区域的说明:
- 从菜单或工具栏中选择所需的绘图模式形状。有三种选择:矩形
、椭圆
或圆角矩形
。
- 在主窗口上选择一个区域,然后开始拖动该区域。将出现一个橡皮筋效果,显示该区域将出现的位置。
- 使用左鼠标按钮为源 1 区域绘制形状。
使用右鼠标按钮为源 2 区域绘制形状。 - 您可以随时按 Escape 键取消绘图操作。
- 松开鼠标按钮,即可使用您创建的新形状更新区域。
- 源 1 区域将以红色绘制,源 2 区域将以蓝色绘制。
在绘制区域的窗口右侧,有四个子视图,用于演示不同的组合模式:RGN_AND、RGN_DIFF、RGN_OR、RGN_XOR
。每次修改源区域时,这些子视图都会更新。可以通过将子视图结果拖动到显示源区域的窗口来替换当前的源区域之一。源 1 和源 2 区域分别以红色和蓝色显示,与主视图相同,新组合的区域将以紫色显示。
以下是将组合区域移动到源区域的说明:
- 只需决定您想使用四个子视图中的哪一个。
- 单击子视图并将其拖到主窗口。将出现一个图标,表示正在拖动该项目。
- 使用左鼠标按钮替换源 1 区域的组合区域。
使用右鼠标按钮替换源 2 区域的组合区域。 - 您可以随时按 Escape 键取消替换操作。
- 松开鼠标按钮,即可使用拖动的组合区域替换区域。
您可以选择删除 Source1
、Source2
或两者区域,方法是选择相应的菜单项。
您可以选择查看 Source1
区域、Source2
区域或所有区域,方法是从菜单中选择相应的视图。查看全部 是默认选择。
RgnGuide
程序中的最后一个操作是查看区域分解模式下的组成矩形。您只需选中“分解源 1”或“分解源 2”菜单项即可。然后,视图将显示所选区域分解为组成该区域的每个矩形。每个矩形都将使用交替颜色绘制。一个简单的矩形用实色绘制会很单调。而一个椭圆则会在大约每隔一行扫描线处包含一个新的矩形。
结论
区域是您可以在程序中使用的非常强大的操作系统资源。演示程序仅说明了如何管理资源,还有许多未在此描述的其他用途。WIN32 提供了一套丰富的函数,允许您管理和操作区域。