提问人:OutOfTime 提问时间:8/23/2023 最后编辑:OutOfTime 更新时间:8/30/2023 访问量:87
如何保持 TImage 作为 TImage 背景图像上的标记的相对位置
How to keep relative position of TImage as a Marker on a TImage background image
问:
我正在尝试将许多标记图像放置在 C++ Builder Alexandria 11.3 中的背景图像上。我可以创建它们并放置它们,但如果我调整图像大小,它们就无法保持在同一位置。
编辑:为清楚起见,删除了之前的编辑...
由于这里需要最小代码来演示问题,因此我提交了此代码,该代码被削减到最大,并且在我看来,要求示例中的所有内容构成最小代码,该代码仅包含您的组件托盘上的组件,就像它们在我的组件托盘上一样,请查看问题并提出解决方案(如果可以的话)。
编辑:删除了代码,与问题无关
@Remy,请参阅您的最后一条评论
NewMarkerX = OldMarkerX * (NewImageWidth / OldImageWidth);
NewMarkerY = OldMarkerY * (NewImageHeight / OldImageHeight);
与此相同,其中 m[i]->X = 与 NewMarkerX 相同
for(int i = 0; i < m.size(); i++)
{
//DrawnMarkerX = (OriginalMarkerX * DrawnImageWidth) / OriginalImageWidth;
//DrawnMarkerY = (OriginalMarkerY * DrawnImageHeight) / OriginalImageHeight;
//DrawnMarkerX = (m[i]->X * newImageWidth ) / oldImageWidth;
//DrawnMarkerY = (m[i]->Y * newImageHeight ) / oldImageHeight;
m[i]->X = (m[i]->X * newImageWidth ) / oldImageWidth;
m[i]->Y = (m[i]->Y * newImageHeight ) / oldImageHeight;
//SetBkMode(Canvas->Handle, TRANSPARENT);
Canvas->TextOutW(m[i]->image->Left + 10, m[i]->image->Top + 10, IntToStr(m[i]->image->Left) + "," + IntToStr(m[i]->image->Top));
Canvas->TextOutW(m[i]->image->Left + 10, m[i]->image->Top + 10, IntToStr(m[i]->image->Left) + "," + IntToStr(m[i]->image->Top));
Canvas->TextOutW(50, 50, IntToStr((int)newImageWidth) + "," + IntToStr((int)newImageHeight));
}
这是正确的吗,如果是这样,它不起作用,我已经探索了其他可能性,但不会深入探讨,因为它们已经很多了。
干杯
答:
0赞
Remy Lebeau
8/24/2023
#1
在调整大小时,您知道背景图像的新旧大小,因此很容易计算出新的标记位置。只需将新图像宽度除以旧图像宽度,然后将标记的旧 X 位置乘以该值即可。对图像高度和标记 Y 位置重复上述步骤:
NewMarkerX = OldMarkerX * (NewImageWidth / OldImageWidth);
NewMarkerY = OldMarkerY * (NewImageHeight / OldImageHeight);
艺术
NewMarkerX = (OldMarkerX * NewImageWidth) / OldImageWidth;
NewMarkerY = (OldMarkerY * NewImageHeight) / OldImageHeight;
另一种方法是根本不使用手动定位的控件。请改用。在这种情况下,您可以先以所需的大小绘制背景图像,然后使用类似的公式在相对于该图像大小的适当位置绘制每个标记:TImage
TPaintBox
OnPaint
DrawnMarkerX = OriginalMarkerX * (DrawnImageWidth / OriginalImageWidth);
DrawnMarkerY = OriginalMarkerY * (DrawnImageHeight / OriginalImageHeight);
艺术
DrawnMarkerX = (OriginalMarkerX * DrawnImageWidth) / OriginalImageWidth;
DrawnMarkerY = (OriginalMarkerY * DrawnImageHeight) / OriginalImageHeight;
评论
0赞
OutOfTime
8/24/2023
我明白你在说什么,昨晚我正朝着那个方向前进,但已经很晚了,所以上床睡觉了,你提出的很简单,但没有对 TPaintBox 做任何工作,我正在努力获得适合油漆盒尺寸的初始尺寸,但图像尺寸比油漆盒尺寸大得多, 我看起来可能还不够难,但似乎可以找到如何通过 TGraphic 调整油漆盒的大小,这可能很简单,但我没有得到它(像往常一样)
0赞
VLL
8/24/2023
@OutOfTime 您不必调整油漆盒的大小。如果您使用的是 Windows,请使用 获取本机句柄(与图像相同)并使用 WinAPI 函数进行绘制。如果图像数据始终相同,则可以将 TImage 保留在窗体上 (Visible = False) 并从中复制。 将绘制图像,同时将其拉伸到油漆盒画布大小。learn.microsoft.com/en-us/windows/win32/api/wingdi/......box->Canvas->Handle
StretchBlt()
0赞
Remy Lebeau
8/24/2023
无需直接使用 Win32 API。PaintBox 具有通过拉伸绘制图像的方法。只需将背景图像和标记加载到内存中,然后将它们绘制到具有所需位置和大小的位置。您可以通过简单地拉伸绘图来放大和缩小 PaintBox。使用 PaintBox 的方法触发重绘,然后在下一个事件中使用更新的位置/大小重新绘制。Canvas
Canvas
Invalidate()
OnPaint
0赞
OutOfTime
8/25/2023
好的,使用 TPanel 的 OnResize 方法调整图像大小工作正常,所以在这一点上,我的兴趣是将标记从数据库重新定位到首次应用标记的背景图像上。使用 Remy 的代码对我不起作用,在我的 OP 编辑部分使用代码可以使标记保持在它们放置的位置,但不在相对于它们放置的图像的位置,您想查看 who 表单代码吗,它可能会有所帮助。
1赞
OutOfTime
8/25/2023
谢谢雷米,我同意你说的话,如果没有我的病情,我认为你已经知道了,否则,它是 4 期晚期癌症,它进入我的骨头,影响我的脊柱和神经病变,再次,我不是在寻求同情,我知道你明白,容易得多的是没有一点困难,我很难完成我的项目以帮助已经表明急需的医疗工业去 mbp.bcbhelper.com/sample-page。我意识到的一件事是我没有缩放图像,它只是根据 align 属性调整了大小
评论