I had a look at the implementation, and the extra gap is actually not caused by additional space characters. It comes from this code:
if FTimeWidth > 0 then
R.Right := R.Right + 2 * FDigitWidth;
where
FDigitWidth is calculated as the maximum width of the characters
0 through
9 in the current font. So the separator width is effectively hardcoded to twice the width of the widest digit.
In my local copy, I simply changed this to use the width of a single space, and it produces the appearance I need.
if FTimeWidth > 0 then
R.Right := R.Right + Canvas.TextWidth(' ');
The only remaining issue is that the mouse hit-testing still uses the hardcoded 2 * FDigitWidth spacing. It should use the same configurable spacing as the rendering code.
To keep the mouse hit-testing in sync with the rendering, the following code in
TCustomDateTimePicker.SelectTextPartUnderMouse should also be updated:
if NX >= FDateWidth + FDigitWidth then
begin
InTime := True;
NX := NX - FDateWidth - 2 * FDigitWidth;
end;
to use the same spacing value as the rendering code, for example:
Gap := Canvas.GetTextWidth(' ');
if NX >= FDateWidth + Gap then
begin
InTime := True;
NX := NX - FDateWidth - Gap;
end;
This ensures that the mouse hit-testing uses the same spacing as the rendering.
My use case is that I use
TDateTimePicker as an in-place editor inside a grid cell. When editing starts, the time shifts noticeably to the right because of this large gap. This creates an undesirable visual artifact, as the contents of the edited cell no longer line up with the other cells in the grid.
I'm not suggesting changing the default behavior. However, it would be very useful if this spacing could be made configurable. For example, by exposing the gap width as a property, or at least making the calculation virtual/protected so descendant classes can override it without having to maintain a patched copy of the entire unit.