首页 > 解决方案 > GDI - OffsetRgn() 函数的意外结果

问题描述

我正在使用 Embarcadero RAD Studio C++ builder XE7。

对于使用 Windows GDI 的绘图功能,我需要将剪辑区域添加到画布的设备上下文中。

通过测试我的代码,我注意到有时剪辑区域小于预期大小。我搜索了原因,发现 OffsetRgn() 函数有一个奇怪的行为,这让我有点困惑。

要应用剪辑区域,我使用类似于以下的代码:

std::unique_ptr<TBitmap> pBitmap(new TBitmap());
pBitmap->PixelFormat = pf32bit;
pBitmap->AlphaFormat = afDefined;
pBitmap->SetSize(60, 7);

TCanvas* pCanvas = pBitmap->Canvas;

::SelectClipRgn(pCanvas->Handle, NULL);

const TRect sourceRect = pCanvas->ClipRect;

HRGN pClipRegion = ::CreateRectRgn(50, -2, 60, 8);

::SelectClipRgn(pCanvas->Handle, pClipRegion);

const TRect intermediateRect = pCanvas->ClipRect;

const int deltaX = pCanvas->ClipRect.Left - 50;
const int deltaY = pCanvas->ClipRect.Top  - (-2);

::OffsetRgn(pClipRegion, -deltaX, -deltaY);

::SelectClipRgn(pCanvas->Handle, pClipRegion);

const TRect finalRect = pCanvas->ClipRect;

像这样写的注释,在他的上下文之外,上面的代码并没有真正的意义,我知道这是不合逻辑的。请不要评判它的质量,这不是我提问的目的。我收集了几个摘录,我将它们组合成一个可执行代码来提出问题。

硬编码值是问题发生时我在应用程序中获得的值的一个示例。如果我执行上面的代码,我会测量:

然而,我希望 finalRect 中的底部值也应该等于 7,这是画布限制,因为我只移动了该区域而没有其他任何内容。那么为什么它的价值突然变得比预期的要小呢?

标签: gdiregioncliprad-studio

解决方案


所以我终于找到了案件的实质。基于这篇文章:

为什么在 GetClipRgn 的结果上调用 GetRgnBox 会返回与 GetClipRect 完全不同的矩形?

剪辑区域以相对于画布原点的逻辑单位应用,而我尝试应用的剪辑矩形是以 [0, 0] 原点的像素为单位测量的。

由于我在代码中错误地认为两个系统的原点始终为 [0, 0],因此在几种特殊情况下生成的区域可能不正确,导致我有时注意到在实际应用的剪辑和我预期的剪辑之间发生了这种奇怪的转变。

使用 GetWindowOrgEx() 函数测量画布原点突出显示了该问题。

但是对于上面显示的情况,问题出现了,因为剪辑区域移动了 -2 的偏移量,因此顶部的值为 -4,底部的值为 6,然后在剪辑区域为应用,导致顶部值为 0,底部值为 6 的剪辑。


推荐阅读