So I've spent a whole load of time trying to render some text. I finally managed to get somewhere by subclassing the ListView and adding a WndProc override as follows:
protected override void WndProc(ref Message m) { base.WndProc( ref m );
//NM_CUSTOMDRAW =-12
switch( m.Msg )
{
case 0x004e://WM_NOTIFY:
case 0x204e://WM_REFLECT_NOTIFY
{
NMHDR nmhdr = (NMHDR)System.Runtime.InteropServices.Marshal.PtrToStructure( m.LParam, typeof( NMHDR ) );
if ( nmhdr.code == -12 ) //NM_CUSTOMDRAW
{
NMLVCUSTOMDRAW nmlvcd = (NMLVCUSTOMDRAW)System.Runtime.InteropServices.Marshal.PtrToStructure( m.LParam, typeof( NMLVCUSTOMDRAW ) );
System.Diagnostics.Trace.WriteLine( nmlvcd.nmcd.dwDrawStage.ToString() );
if ( nmlvcd.nmcd.dwDrawStage == 1 ) //CDDS_PREPAINT
{
int result = (int)m.Result;
result |= 0x10;//CDRF_NOTIFYPOSTPAINT;
m.Result = (IntPtr)result;
}
else if ( nmlvcd.nmcd.dwDrawStage == 2 ) //CDDS_POSTPAINT
{
Graphics g = Graphics.FromHdc( nmlvcd.nmcd.hdc );
if ( DrawFloatingItem != null )
{
PaintEventArgs pe = new PaintEventArgs( g, nmlvcd.nmcd.rc );
DrawFloatingItem( this, pe );
}
}
else if ( nmlvcd.nmcd.dwDrawStage == 65537 ) //CDDS_ITEMPREPAINT
{
int result = (int)m.Result;
result |= 0x10;//CDRF_NOTIFYPOSTPAINT;
m.Result = (IntPtr)result;
}
else if ( nmlvcd.nmcd.dwDrawStage == 65538 ) //CDDS_ITEMPOSTPAINT
{
}
}
}
break;
}
}
With this I've successfully managed to render over the list view. However the moment I do render (From the DrawFloatingItem event) then all the items shift up by the header's height (ie the first item is rendererd under the column header).
This is the list before:
And this is the list afterwards:
Has anyone got any idea what I am doing wrong here? If I comment out my draw commands (inside the "DrawFloatingItem" function) then everything works as expected. However the moment I do any drawing then the rendering goes wrong as above.
Any help would be massively appreciated!
Its typical I always figure it out shortly after posting up a question. My mistake was that I wasn't disposing of the Graphics object I was creating before caling my DrawFloatingItem event.
Changing to the following fixed the problem:
using( Graphics g = Graphics.FromHdc( nmlvcd.nmcd.hdc ) )
{
if ( DrawFloatingItem != null )
{
PaintEventArgs pe = new PaintEventArgs( g, nmlvcd.nmcd.rc );
DrawFloatingItem( this, pe );
}
}