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

WIN32 区域指南

starIconstarIconstarIconstarIconstarIcon

5.00/5 (37投票s)

2002年3月11日

CPOL

8分钟阅读

viewsIcon

274491

downloadIcon

8300

关于如何使用 WIN32 SDK 创建和使用区域的指南

Sample Image - preview.gif

引言

区域是 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_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_OR
RGN_XOR 创建两个组合区域的并集,但不包括任何重叠区域。
CombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, RGN_XOR);
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 对象的内部表示。区域中的每个矩形都使用交替颜色的画笔进行绘制。

Internal Representation of a region.

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. 在主窗口上选择一个区域,然后开始拖动该区域。将出现一个橡皮筋效果,显示该区域将出现的位置。
  3. 使用鼠标按钮为源 1 区域绘制形状。
    使用鼠标按钮为源 2 区域绘制形状。
  4. 您可以随时按 Escape 键取消绘图操作。
  5. 松开鼠标按钮,即可使用您创建的新形状更新区域。
  6. 源 1 区域将以红色绘制,源 2 区域将以蓝色绘制。

在绘制区域的窗口右侧,有四个子视图,用于演示不同的组合模式:RGN_AND、RGN_DIFF、RGN_OR、RGN_XOR。每次修改源区域时,这些子视图都会更新。可以通过将子视图结果拖动到显示源区域的窗口来替换当前的源区域之一。源 1 和源 2 区域分别以红色和蓝色显示,与主视图相同,新组合的区域将以紫色显示。

以下是将组合区域移动到源区域的说明:

  1. 只需决定您想使用四个子视图中的哪一个。
  2. 单击子视图并将其拖到主窗口。将出现一个图标,表示正在拖动该项目。
  3. 使用鼠标按钮替换源 1 区域的组合区域。
    使用鼠标按钮替换源 2 区域的组合区域。
  4. 您可以随时按 Escape 键取消替换操作。
  5. 松开鼠标按钮,即可使用拖动的组合区域替换区域。

您可以选择删除 Source1Source2 或两者区域,方法是选择相应的菜单项。

您可以选择查看 Source1 区域、Source2 区域或所有区域,方法是从菜单中选择相应的视图。查看全部 是默认选择。

RgnGuide 程序中的最后一个操作是查看区域分解模式下的组成矩形。您只需选中“分解源 1”或“分解源 2”菜单项即可。然后,视图将显示所选区域分解为组成该区域的每个矩形。每个矩形都将使用交替颜色绘制。一个简单的矩形用实色绘制会很单调。而一个椭圆则会在大约每隔一行扫描线处包含一个新的矩形。

结论

区域是您可以在程序中使用的非常强大的操作系统资源。演示程序仅说明了如何管理资源,还有许多未在此描述的其他用途。WIN32 提供了一套丰富的函数,允许您管理和操作区域。

© . All rights reserved.