gdi - 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;
像这样写的注释,在他的上下文之外,上面的代码并没有真正的意义,我知道这是不合逻辑的。请不要评判它的质量,这不是我提问的目的。我收集了几个摘录,我将它们组合成一个可执行代码来提出问题。
硬编码值是问题发生时我在应用程序中获得的值的一个示例。如果我执行上面的代码,我会测量:
- 在 sourceRect 值中,left = 0,top = 0,right = 60,bottom = 7
- left = 50, top = 0, right = 60, bottom = 7 in intermediateRect 值
- 左 = 50,上 = 0,右 = 60,下 = 6在 finalRect
然而,我希望 finalRect 中的底部值也应该等于 7,这是画布限制,因为我只移动了该区域而没有其他任何内容。那么为什么它的价值突然变得比预期的要小呢?
解决方案
所以我终于找到了案件的实质。基于这篇文章:
为什么在 GetClipRgn 的结果上调用 GetRgnBox 会返回与 GetClipRect 完全不同的矩形?
剪辑区域以相对于画布原点的逻辑单位应用,而我尝试应用的剪辑矩形是以 [0, 0] 原点的像素为单位测量的。
由于我在代码中错误地认为两个系统的原点始终为 [0, 0],因此在几种特殊情况下生成的区域可能不正确,导致我有时注意到在实际应用的剪辑和我预期的剪辑之间发生了这种奇怪的转变。
使用 GetWindowOrgEx() 函数测量画布原点突出显示了该问题。
但是对于上面显示的情况,问题出现了,因为剪辑区域移动了 -2 的偏移量,因此顶部的值为 -4,底部的值为 6,然后在剪辑区域为应用,导致顶部值为 0,底部值为 6 的剪辑。
推荐阅读
- javascript - 为什么即使使用钩子更新父状态,子组件也不重新渲染
- vue.js - 如何在 vuetify select 中添加自定义按钮
- python - 如何解决 PyTest 中的过时元素异常
- javascript - 将对象作为函数调用 JavaScript
- variables - Verilog:寄存器的使用:值何时实际更新?
- c++ - 访问指向另一个类中的指针对象的指针
- mysql - 无法将 MYSQL 与 Django settings.py 正确连接
- mysql - 查询中的Mysql字段和数据类型
- javascript - 检查哪个孩子在视口中?
- javascript - 为什么我的字体/布局在生产时会发生变化?尝试过 Netlify 和 Github 页面