Delphi VCL: Owner drawing a TStringGrid

Embarcadero has broken owner drawing of TStringGrid several times. To get the text positioned correctly you need version-specific X and Y offsets. Here is the case statement GExperts uses (from GX_StringGridDrawFix.pas):

procedure DetermineTextOffsets(_Focused: Boolean; out _XOffset, _YOffset: Integer);
begin
  case GetBorlandIdeVersion of
    ideD600..ideRSXE1U1: begin
      // Versions before XE2 worked fine with an offset of 2 for both, x and y
      _XOffset := 2;
      _YOffset := 2;
    end;
    ideRSXE2..ideRS103U3: begin
      // from XE2 onwards we need a different y offset
      _XOffset := 2;
      _YOffset := 0;
    end;
    ideRS104: begin
      // fix for original bug in Delphi 10.4
      _XOffset := 0;
      _YOffset := 0;
    end;
    ideRS104P2: begin
      // Embarcadero managed to bungle the StringGrid redraw fix in RS 10.4 patch 2.
      // Now we have to check whether the grid is focused and use a different x offset in that case.
      if _Focused then begin
        _XOffset := 6;
        _YOffset := 2;
      end else begin
        _XOffset := 2;
        _YOffset := 2;
      end;
    end;
    ideRS104U1, ideRS104U2: begin
      // in RS 10.4 Update 1 they apparently fixed the fix (or at least made it consistently wrong again)
      _XOffset := 6;
      _YOffset := 2;
    end;
    ideRS11..ideRS12U1: begin
      _XOffset := 6;
      _YOffset := 2;
    end;
  else
    // we optimistically assume that they won't break it again in future versions
    _XOffset := 6;
    _YOffset := 2;
  end;
end;

These offsets are then applied in the drawing procedure:

cnv.TextRect(_Rect, _Rect.Left + XOffset, _Rect.Top + YOffset, _Text);

The full unit is in the GExperts repository as Source/Utils/GX_StringGridDrawFix.pas. It is also possible that this misbehavior is restricted to projects using runtime packages, such as IDE plugins. I have not extensively tested it outside of that context. And I have not tested the C#Builder, C++Builder, or Kylix variants at all, but the code assumes they behave like pre-XE2 Delphi (X=2, Y=2). If anyone still using those finds otherwise, let me know.