I have to work with C++Builder. Depending on the mood, the IDE changes the hex-encoded bitmap property within the DFM file. Even if I have not changed anything within the GUI.
I'm using GIT and all the time this will result in a diff of the .dfm (which is ugly).
It is a VCL project with some Forms. The Bitmap value which will change randomly is from a TImageList.
Is there a way to prevent that the IDE will change the DFM all the time?

This is a known issue.
Originally reported in XE, and closed as "Wont Do" (archived link):
QC 92769: bitmap data of TImageList in dfm changes everytime the form is viewed as text (alt-F12)
Then later, reported again in XE8, and closed as fixed in 10.3, at least for VCL:
RSP-13666: Bitmap data of TImageList changes constantly
So, to answer your question - make sure you are using C++Builder 10.3 or later, as the problem has already been corrected.
At least for VCL, anyway. There is a similar report still open for FMX:
RSP-11259: Every FMX form save changes binary image data in FMX
Some background info:
Internally, the
Bitmapproperty is streamed through the DFM system using theTFiler::DefineBinaryProperty()method. This causes the DFM system to use an internalTMemoryStreamfor reading/writing theBitmapdata from/into the DFM.TImageListdoes not actually hold a bitmap image, it holds a Win32ImageListcontrol as anHIMAGELISThandle (stored in theTImageList::Handleproperty). The Win32 API deals with the actual bitmap internally.When writing to the DFM,
TImageListwraps theTMemoryStreamwith aTStreamAdapterto get a Win32IStreaminterface, and then calls the Win32ImageList_Write/Ex()function to write theHIMAGELIST's data into theTMemoryStream(in a pre-ComCtrl32v6 format), and then the bytes in theTMemoryStreamare written into the DFM. The bytes49 4Cat the beginning of theBitmapdata are an identifier for the Win32 API'sILstream format, and the bytes42 4Dare an identifier for the actual bitmap image that theHIMAGELISTholds.In your screenshot, there is only 1 byte being changed (in other past reports, there were more bytes being changed). According to this WineHQ code (and various other 3rd party repos that I found), that changed byte belongs to the
ILHEAD::cGrowfield of theHIMAGELIST's stream header:Which corresponds to the
TImageList::AllocByproperty:When
TImageListis writing itsHIMAGELISTto the DFM, it first lets Windows write theHIMAGELISTdata to theIStreamhowever it wants. Then, sometime between XE4 and 10.3 (I don't have sources to pinpoint the exact version), new logic was added to haveTImageListthen go back and overwrite thecGrowvalue with its ownAllocByvalue instead. This was added to address this issue mentioned in RSP-13666:In that "previous issue" (QC #92769), it says:
Which is exactly what you are seeing happen - the earlier
cGrowvalue of78 02(632) being replaced with a new value of7C 02(636).The QC ticket also says:
And:
And, as noted above,
TImageListdoes useImageList_WriteEx()when writing to a DFM stream. And Embarcadero eventually decided to take the risk and patch the stream data thatImageList_WriteEx()writes.