The DataGridViewRowPostPaintEventArgs includes this particular PaintHeader method:
PaintHeader(DataGridViewPaintParts) - Paints the specified parts of the row header of the current row.
This is the DataGridViewPaintParts Enumeration:
https://msdn.microsoft.com/en-us/library/ms159092%28v=vs.110%29.aspx
So what you do is in your datagridview's RowPostPaint event, first tell it to only paint the background of the row's header...like so:
e.PaintHeader(DataGridViewPaintParts.Background)
Then tell it to draw in whatever string you want it to. Here is my example:
Private Sub MyDGV_RowPostPaint(sender As Object, e As DataGridViewRowPostPaintEventArgs) Handles dgvData.RowPostPaint
Dim grid As DataGridView = DirectCast(sender, DataGridView)
e.PaintHeader(DataGridViewPaintParts.Background)
Dim rowIdx As String = (e.RowIndex + 1).ToString()
Dim rowFont As New System.Drawing.Font("Segoe UI", 9.0!, _
System.Drawing.FontStyle.Bold, _
System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Dim centerFormat = New StringFormat()
centerFormat.Alignment = StringAlignment.Far
centerFormat.LineAlignment = StringAlignment.Near
Dim headerBounds As Rectangle = New Rectangle(e.RowBounds.Left, e.RowBounds.Top, grid.RowHeadersWidth, e.RowBounds.Height)
e.Graphics.DrawString(rowIdx, rowFont, SystemBrushes.ControlText, headerBounds, centerFormat)
End Sub