如何防止Embarcadero C++Builder一直更改DFM中的位图代码?

问题描述 投票:0回答:1

我必须使用 C++Builder。根据心情,IDE 会更改 DFM 文件中的十六进制编码位图属性。即使我没有在 GUI 中更改任何内容。

我一直在使用 GIT,这将导致

.dfm
(很难看)的差异。

这是一个带有一些表格的VCL项目。随机变化的

Bitmap
值来自
TImageList
.

有什么办法可以防止IDE一直改DFM吗?

c++builder vcl dfm
1个回答
0
投票

这是一个已知问题。

最初在 XE 中报告,并作为“Wont Do”关闭(存档链接):

QC 92769:每次将表单视为文本时,dfm 中 TImageList 的位图数据都会发生变化(alt-F12)

后来又在XE8报错了,10.3就固定关闭了,至少VCL是这样的:

RSP-13666:TImageList 的位图数据不断变化

所以,要回答你的问题——确保你使用的是 C++Builder 10.3 或更高版本,因为问题已经得到纠正。

无论如何,至少对于 VCL 而言。 FMX 仍有类似的报告:

RSP-11259:每个 FMX 表单保存都会更改 FMX 中的二进制图像数据


一些背景资料:

在内部,

Bitmap
属性使用
TFiler::DefineBinaryProperty()
方法通过 DFM 系统流式传输。这会导致 DFM 系统使用内部
TMemoryStream
从/向 DFM 读取/写入
Bitmap
数据。

TImageList
实际上并不包含位图图像,它包含一个 Win32
ImageList
控件
作为
HIMAGELIST
句柄(存储在
TImageList::Handle
属性中)。 Win32 API 在内部处理实际的位图。

写入DFM时,

TImageList
TMemoryStream
包裹
TStreamAdapter
得到Win32
IStream
接口,然后调用Win32
ImageList_Write/Ex()
函数将
HIMAGELIST
的数据写入
 TMemoryStream
(pre-ComCtrl32v6格式),然后将
TMemoryStream
中的字节写入DFM。
49 4C
数据开头的字节
Bitmap
是Win32 API的
IL
流格式的标识符,字节
42 4D
HIMAGELIST
保存的实际位图图像的标识符。

在您的屏幕截图中,只有 1 个字节被更改(在过去的其他报告中,有更多字节被更改)。根据 this WineHQ 代码(以及我发现的各种其他第 3 方回购协议),更改的字节属于

ILHEAD::cGrow
流标头的
HIMAGELIST
字段:

当系统需要为新图像腾出空间时,图像列表可以增长的图像数量。该参数表示调整后的图像列表可以包含的新图像的数量。

对应

TImageList::AllocBy
属性:

设置图像列表在需要为新图像腾出空间时增长的图像数量。

TImageList
将其
HIMAGELIST
写入 DFM 时,它首先让 Windows 根据需要将
HIMAGELIST
数据写入
IStream
。然后,在 XE4 和 10.3 之间的某个时间(我没有消息来源来确定确切的版本),添加了新逻辑以具有
TImageList
然后返回并用它自己的
cGrow
值覆盖
AllocBy
值。添加此内容是为了解决 RSP-13666 中提到的这个问题:

在上一期的最后评论中,您指出问题的根本原因是

ImageList_WriteEx
API 似乎更新了一个未记录的计数器。这与我自己对该问题的调查一致。

在那个“上一期”(QC #92769)中,它说:

Wine 写入一个 _ILHEAD 结构,该结构中发生变化的违规字节是 WORD cMaxImage 和 WORD cGrow。这些对应于列表中当前分配的图像数量,理论上,一旦您添加超过该数量,列表将增长多少。 每次流式传输图像列表时,cGrow 似乎都会增加 4,这让我觉得 Windows 可能实际上并没有使用该字段。

这正是您所看到的 -

cGrow
(632) 的早期
78 02
值被替换为
7C 02
(636) 的新值。

QC票还写着:

似乎 事后调整流并将其更改为 0 不会立即中断它。但正如我们所说,这似乎有风险

和:

  • 不幸的是,报告的问题是由本机 Win32 ImageList 控件引起的,该控件恰好在方法 ImageList_WriteEx() 中找到,它将图像列表写入流。它不是 Rad Studio 错误,那么它的解决方案不是简单的修复。

  • 微软报告了一个与此问题相关的错误(ID:428868),但在 VS 中

并且,如上所述,

TImageList
在写入 DFM 流时确实使用了
ImageList_WriteEx()
。而 Embarcadero 最终决定冒险并修补
ImageList_WriteEx()
写入的流数据。

© www.soinside.com 2019 - 2024. All rights reserved.