Problem
You need to take into account several factors for each cell:
- The DataGridViewContentAlignment.
- The exact size of the selected characters.
- The zero-width characters (white spaces).
- The size of the content.
- The empty space.
- The index of the first occurrence of the search string.
All the mentioned are necessary to calculate and adjust both the location and size of the highlight rectangle.
Here's an example:
RTL Languages - RTL Layout
private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (txtSearch.TextLength < 1
|| e.RowIndex < 0
|| e.ColumnIndex < 1
|| e.Value == null)
return;
var zeroWidth = "|";
var v = e.Value.ToString().Replace(" ", zeroWidth);
var f = txtSearch.Text.Replace(" ", zeroWidth);
var i = v.IndexOf(f, StringComparison.InvariantCultureIgnoreCase);
if (i < 0) return;
e.Handled = true;
var g = e.Graphics;
using (var sf = ToStringFormat(e.CellStyle.Alignment))
{
var zw = g.MeasureString(zeroWidth, e.CellStyle.Font, e.CellBounds.Width, sf).Width;
var valWidth = g.MeasureString(v, e.CellStyle.Font, e.CellBounds.Width, sf).Width;
var w = g.MeasureString(f, e.CellStyle.Font, e.CellBounds.Width, sf).Width;
var x = e.CellBounds.Right - ((e.CellBounds.Width - valWidth) / 2);
x -= g.MeasureString(v.Substring(0, i), e.CellStyle.Font,
e.CellBounds.Width, sf).Width;
x -= w;
switch (e.CellStyle.Alignment)
{
case DataGridViewContentAlignment.BottomLeft:
case DataGridViewContentAlignment.MiddleLeft:
case DataGridViewContentAlignment.TopLeft:
x += ((e.CellBounds.Width - valWidth) / 2) - zw;
break;
case DataGridViewContentAlignment.MiddleRight:
case DataGridViewContentAlignment.BottomRight:
case DataGridViewContentAlignment.TopRight:
x -= ((e.CellBounds.Width - valWidth) / 2) - zw;
break;
default:
break;
}
var r = new RectangleF(
x,
e.CellBounds.Y + 3,
w,
e.CellBounds.Height - 7);
e.PaintBackground(e.CellBounds, true);
g.FillRectangle(Brushes.Yellow, r);
e.PaintContent(e.CellBounds);
}
}
private StringFormat ToStringFormat(DataGridViewContentAlignment ca)
{
var sf = StringFormat.GenericTypographic;
switch (ca)
{
case DataGridViewContentAlignment.MiddleCenter:
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
break;
case DataGridViewContentAlignment.MiddleLeft:
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Center;
break;
case DataGridViewContentAlignment.MiddleRight:
sf.Alignment = StringAlignment.Far;
sf.LineAlignment = StringAlignment.Center;
break;
case DataGridViewContentAlignment.BottomCenter:
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Far;
break;
case DataGridViewContentAlignment.BottomLeft:
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Far;
break;
case DataGridViewContentAlignment.BottomRight:
sf.Alignment = StringAlignment.Far;
sf.LineAlignment = StringAlignment.Far;
break;
case DataGridViewContentAlignment.TopLeft:
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Near;
break;
case DataGridViewContentAlignment.TopRight:
sf.Alignment = StringAlignment.Far;
sf.LineAlignment = StringAlignment.Near;
break;
case DataGridViewContentAlignment.TopCenter:
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Near;
break;
}
sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
return sf;
}
Here's a demo.

Note: Only the DGV is set to RTL layout in the demo.
LTR Languages - LTR Layout
Maybe out of scope, however might be useful for someone.
private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (txtSearch.TextLength < 1
|| e.RowIndex < 0
|| e.ColumnIndex < 1
|| e.Value == null)
return;
var zeroWidth = "|";
var v = e.Value.ToString().Replace(" ", zeroWidth);
var f = txtSearch.Text.Replace(" ", zeroWidth);
var i = v.IndexOf(f, StringComparison.InvariantCultureIgnoreCase);
if (i < 0) return;
e.Handled = true;
var g = e.Graphics;
using (var sf = ToStringFormat(e.CellStyle.Alignment))
{
var zs = g.MeasureString(zeroWidth, e.CellStyle.Font,
e.CellBounds.Width, sf).Width;
var valWidth = g.MeasureString(v, e.CellStyle.Font,
e.CellBounds.Width, sf).Width;
var x = g.MeasureString(v.Substring(0, i), e.CellStyle.Font,
e.CellBounds.Width, sf).Width;
var w = g.MeasureString(v.Substring(i, f.Length), e.CellStyle.Font,
e.CellBounds.Width, sf).Width;
switch (e.CellStyle.Alignment)
{
case DataGridViewContentAlignment.MiddleCenter:
case DataGridViewContentAlignment.BottomCenter:
case DataGridViewContentAlignment.TopCenter:
x += (e.CellBounds.Width - valWidth) / 2;
x -= zs / 2;
break;
case DataGridViewContentAlignment.MiddleRight:
case DataGridViewContentAlignment.BottomRight:
case DataGridViewContentAlignment.TopRight:
x += (e.CellBounds.Width - valWidth);
x -= zs * 1.5f;
break;
default:
x += zs / 2;
break;
}
var r = new RectangleF(
e.CellBounds.X + x,
e.CellBounds.Y + 3,
w,
e.CellBounds.Height - 7);
e.PaintBackground(e.CellBounds, true);
g.FillRectangle(Brushes.Yellow, r);
e.PaintContent(e.CellBounds);
}
}
private StringFormat ToStringFormat(DataGridViewContentAlignment ca)
{
var sf = StringFormat.GenericTypographic;
switch (ca)
{
case DataGridViewContentAlignment.MiddleCenter:
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
break;
case DataGridViewContentAlignment.MiddleLeft:
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Center;
break;
case DataGridViewContentAlignment.MiddleRight:
sf.Alignment = StringAlignment.Far;
sf.LineAlignment = StringAlignment.Center;
break;
case DataGridViewContentAlignment.BottomCenter:
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Far;
break;
case DataGridViewContentAlignment.BottomLeft:
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Far;
break;
case DataGridViewContentAlignment.BottomRight:
sf.Alignment = StringAlignment.Far;
sf.LineAlignment = StringAlignment.Far;
break;
case DataGridViewContentAlignment.TopLeft:
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Near;
break;
case DataGridViewContentAlignment.TopRight:
sf.Alignment = StringAlignment.Far;
sf.LineAlignment = StringAlignment.Near;
break;
case DataGridViewContentAlignment.TopCenter:
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Near;
break;
}
return sf;
}
