Thursday, July 19, 2007

how to change the listview selected color ?

one of my colleges asked me that question and i though its the windows default selected color and you can't change it?? i did a google search for this nothing came up; so after spending serious amout of time i came up with this. million with sample where you can't find it anywhere else. this is a combination of a some russian , japanies coding..
=====================================

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace listviewsample
{
public partial class Form1 : Form
{


public static int WM_NOTIFY = 0x004E;
public static int NM_FIRST = 0- 0;
public static int NM_CUSTOMDRAW = NM_FIRST-12;
public static int CDRF_DODEFAULT = 0x00000000;
public static int CDRF_NEWFONT = 0x00000002;
public static int CDRF_SKIPDEFAULT = 0x00000004;
public static int CDRF_NOTIFYPOSTPAINT = 0x00000010;
public static int CDRF_NOTIFYITEMDRAW = 0x00000020;
public static int CDRF_NOTIFYSUBITEMDRAW = 0x00000020;
public static int CDRF_NOTIFYPOSTERASE = 0x00000040;
public static int CDIS_SELECTED = 0x0001;
public static int CDIS_FOCUS = 0x0010;

public static int CDDS_PREPAINT = 0x00000001;
public static int CDDS_POSTPAINT = 0x00000002;
public static int CDDS_PREERASE = 0x00000003;
public static int CDDS_POSTERASE = 0x00000004;
public static int CDDS_ITEM = 0x00010000;
public static int CDDS_ITEMPREPAINT = CDDS_ITEM | CDDS_PREPAINT;
public static int CDDS_ITEMPOSTPAINT = CDDS_ITEM | CDDS_POSTPAINT;
public static int CDDS_ITEMPREERASE = CDDS_ITEM | CDDS_PREERASE;
public static int CDDS_ITEMPOSTERASE = CDDS_ITEM | CDDS_POSTERASE;
public static int CDDS_SUBITEM = 0x00020000;

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public int hwndFrom;
public int idFrom;
public int code;
}
[StructLayout(LayoutKind.Sequential)]
public struct NMCUSTOMDRAWINFO
{
public NMHDR hdr;
public IntPtr dwDrawStage;
public IntPtr hdc;
public RECT rc;
public IntPtr dwItemSpec;
public uint uItemState;
public IntPtr lItemlParam;
}
[StructLayout(LayoutKind.Sequential)]
public struct NMLVCUSTOMDRAW
{
public NMCUSTOMDRAWINFO nmcd;
public int clrText;
public int clrTextBk;
public int iSubItem;
}

protected override void WndProc(ref Message m)
{
if (m.Msg==WM_NOTIFY && m.WParam.Equals(listView1.Handle))
{
NMHDR nmhdr = (NMHDR)m.GetLParam(typeof(NMHDR));
if (nmhdr.code==NM_CUSTOMDRAW)
{
NMLVCUSTOMDRAW xCustomDraw =
(NMLVCUSTOMDRAW)m.GetLParam(typeof(NMLVCUSTOMDRAW) );
if
(listView1.SelectedIndices.IndexOf(xCustomDraw.nmcd.dwItemSpec.ToInt32())>-1
)
{
if ((xCustomDraw.nmcd.uItemState & CDIS_SELECTED)!=0)
{
xCustomDraw.nmcd.uItemState -= (uint)CDIS_SELECTED;
Marshal.StructureToPtr(xCustomDraw, m.LParam,
false);
}
if
(xCustomDraw.nmcd.dwDrawStage.ToInt32()==CDDS_PREPAINT)
{
m.Result = new IntPtr(CDRF_NOTIFYITEMDRAW);
return;
}
else if
(xCustomDraw.nmcd.dwDrawStage.ToInt32()==CDDS_ITEMPREPAINT)
{
xCustomDraw.clrText = ColorTranslator.ToWin32(Color.Blue);
xCustomDraw.clrTextBk = ((xCustomDraw.nmcd.uItemState & CDIS_FOCUS)!=0) ?
xCustomDraw.clrTextBk = ColorTranslator.ToWin32(Color.Yellow) :
xCustomDraw.clrTextBk = ColorTranslator.ToWin32(Color.Orange);
m.Result = new IntPtr(CDRF_NEWFONT);
Marshal.StructureToPtr(xCustomDraw, m.LParam,
false);
return;
}
}
}
}
base.WndProc(ref m);
}


public Form1()
{
InitializeComponent();
}


}
}

1 comment:

Unknown said...

nice. But where the hell can I set the wanted color?
... and: Is it also possible to get rid of the selected-color after leaving mouseover? There again windows-default-selection color appears.
Greetings,
Joerg