Can't properly handle NM_CUSTOMDRAW in listview

G

Guest

From my understanding, the C# listview class is a wrapper around the win32
listview and all win32 functionality is available through the wndproc method.
I want to modify the C# listview class (change a row's default height and
text color) and the easiest way do this is through custom drawing (I think).
I know this is possible through onpaint but that may be overkill for what I
want to do. I have overriden the listview wndproc and handled the proper
messages. However, I can't get my changes to show up in the listview. The
listview is in detail view. Is their something special I have to do to
enable custom drawing painting? Is their a win32 style I have to enable? I
am receiving the the custom draw messages in CDDS_ITEMPREPAINT and
CDDS_SUBITEM | CDDS_ITEMPREPAINT but my color and height changes don't show
up i the listview UI. Here is my wndproc. All help is appreciated.

protected override void WndProc(ref Message m)
{
int iRow, iCol;
bool bSelected;
NMHDR nmhdr;
NMLVCUSTOMDRAW nmLvDraw;

switch((uint)m.Msg)
{
case OCM_WM_NOTFY:
case WM_NOTIFY:
nmhdr = (NMHDR) m.GetLParam(typeof(NMHDR));
switch(nmhdr.code)
{
case NM_CUSTOMDRAW:
base.WndProc(ref m);
nmLvDraw = (NMLVCUSTOMDRAW) m.GetLParam(typeof(NMLVCUSTOMDRAW));
switch(nmLvDraw.nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
m.Result = (IntPtr) CDRF_NOTIFYITEMDRAW; break;
case CDDS_ITEMPREPAINT:
//below color and pixel
changes won't take
nmLvDraw.clrText = RGB(255, 0, 0);
nmLvDraw.clrTextBk = RGB(0, 255, 0);
nmLvDraw.nmcd.rc.bottom =
0x20;
// m.Result = (IntPtr) CDRF_NEWFONT;
m.Result = (IntPtr) CDRF_NOTIFYSUBITEMDRAW;
// m.Result = (IntPtr) CDRF_DODEFAULT;
break;

case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
//these changes don't take
either
nmLvDraw.clrText = RGB(255, 0, 0);
nmLvDraw.clrTextBk = RGB(0, 255, 0);
nmLvDraw.nmcd.rc.bottom =
0x20;
m.Result = (IntPtr) CDRF_NEWFONT;
break;
}
return;
}
break;
}
base.WndProc(ref m);
}
 
M

Mattias Sjögren

However, I can't get my changes to show up in the listview.

Right now you're just modifying your local copy of the NMLVCUSTOMDRAW
struct. You have to copy the changes back to where lParam points with
Marshal.StructureToPtr().


Mattias
 
M

Mick Doherty

Call base.Wndproc() before modifying the message, not after.

I don't know what you're RGB() method is doing, but it should be returning
something like:
ColorTranslator.ToWin32(Color.Red);

Don't forget to Marshal your modified structure back into m.LParam:
Marshal.StructureToPtr(nmLvDraw, m.LParam, true);

Also you should be looking for the message (WM_REFLECT | WM_NOTIFY) instead
of WM_NOTIFY

I didn't test your code as I'm a bit short on time at the moment, but I
believe it will work with these modifications.
 
G

Guest

Oops, I knew it was something simple...adding Marshal.StructureToPtr did the
job. However I am still unable to change the listview row height in the
CDDS_ITEMPREPAINT case. I am successfully able to change the colors of the
individual listview subitems in the CDDS_SUBITEM | CDDS_ITEMPREPAINT case.
I know the CDDS_ITEMPREPAINT case handles listview rows so I should be able
to modify the listview row height by changing nmLvDraw.nmcd.rc.bottom, right?
Is their another way to change the row height beside this approach using
custom draw?
 
C

Christian ASTOR

johnny said:
I know the CDDS_ITEMPREPAINT case handles listview rows so I should be able
to modify the listview row height by changing nmLvDraw.nmcd.rc.bottom, right?
Is their another way to change the row height beside this approach using
custom draw?

No.
The 2 ways to change the items height of a ListView are by
LVS_OWNERDRAWFIXED style or by changing the font with WM_SETFONT
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top