You can use Custom Draw instead of Owner Draw
For example in this test I draw a Light Gray rectangle in CDDS_ITEMPOSTPAINT event when I double-click on an item
Code in C# as you tagged dotnet-csharp, same code in VB :
Test :
public class ListViewCustom : ListView
{
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct NMHDR
{
public IntPtr hwndFrom;
public IntPtr idFrom;
public int code;
}
[StructLayout(LayoutKind.Sequential)]
private struct NMLISTVIEW
{
public NMHDR hdr;
public int iItem;
public int iSubItem;
public uint uNewState;
public uint uOldState;
public uint uChanged;
public Point ptAction;
public IntPtr lParam;
}
[StructLayout(LayoutKind.Sequential)]
private struct NMCUSTOMDRAW
{
public NMHDR hdr;
public int dwDrawStage;
public IntPtr hdc;
public RECT rc;
public IntPtr dwItemSpec;
public uint uItemState;
public IntPtr lItemlParam;
}
[StructLayout(LayoutKind.Sequential)]
private struct NMLVCUSTOMDRAW
{
public NMCUSTOMDRAW nmcd;
public int clrText;
public int clrTextBk;
public int iSubItem;
public int dwItemType;
public int clrFace;
public int iIconEffect;
public int iIconPhase;
public int iPartId;
public int iStateId;
public RECT rcText;
public uint uAlign;
}
[FlagsAttribute]
private enum CDRF
{
CDRF_DODEFAULT = 0x00000000,
CDRF_NEWFONT = 0x00000002,
CDRF_SKIPDEFAULT = 0x00000004,
CDRF_DOERASE = 0x00000008,
CDRF_SKIPPOSTPAINT = 0x00000100,
CDRF_NOTIFYPOSTPAINT = 0x00000010,
CDRF_NOTIFYITEMDRAW = 0x00000020,
CDRF_NOTIFYSUBITEMDRAW = 0x00000020,
CDRF_NOTIFYPOSTERASE = 0x00000040
}
[FlagsAttribute]
private enum CDDS
{
CDDS_PREPAINT = 0x00000001,
CDDS_POSTPAINT = 0x00000002,
CDDS_PREERASE = 0x00000003,
CDDS_POSTERASE = 0x00000004,
CDDS_ITEM = 0x00010000,
CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT),
CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT),
CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE),
CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE),
CDDS_SUBITEM = 0x00020000
}
[StructLayout(LayoutKind.Sequential)]
private struct LV_ITEM
{
public uint mask;
public int iItem;
public int iSubItem;
public uint state;
public uint stateMask;
public string pszText;
public int cchTextMax;
public int iImage;
public IntPtr lParam;
public int iIndent;
public int iGroupId;
public uint cColumns; // tile view columns
public IntPtr puColumns;
public IntPtr piColFmt;
public int iGroup; // readonly. only valid for owner data.
}
public const int LVM_FIRST = 0x1000;
public const int LVM_SETITEMSTATE = (LVM_FIRST + 43);
public const int LVM_GETITEMSTATE = (LVM_FIRST + 44);
private const int NM_FIRST = 0;
private const int NM_CLICK = (NM_FIRST - 2);
private const int NM_DBLCLK = (NM_FIRST - 3);
private const int NM_RETURN = (NM_FIRST - 4);
private const int NM_RCLICK = (NM_FIRST - 5);
private const int NM_RDBLCLK = (NM_FIRST - 6);
private const int NM_SETFOCUS = (NM_FIRST - 7);
private const int NM_KILLFOCUS = (NM_FIRST - 8);
private const int NM_CUSTOMDRAW = (NM_FIRST - 12);
private const int WM_REFLECT = 0x2000;
private const int WM_NOFITY = 0x004e;
private const int LVIS_FOCUSED = 0x0001;
private const int LVIS_SELECTED = 0x0002;
private const int LVIS_CUT = 0x0004;
private const int LVIS_DROPHILITED = 0x0008;
private const int LVIS_GLOW = 0x0010;
private const int LVIS_ACTIVATING = 0x0020;
private const int LVIS_OVERLAYMASK = 0x0F00;
private const int LVIS_STATEIMAGEMASK = 0xF000;
private static int INDEXTOSTATEIMAGEMASK(int i)
{
return ((i) << 12);
}
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, ref LV_ITEM lParam);
private static void ListView_SetItemState(IntPtr hwndLV, int i, uint state, uint mask)
{
LV_ITEM lvi = new LV_ITEM();
lvi.stateMask = mask;
lvi.state = state;
SendMessage(hwndLV, LVM_SETITEMSTATE, i, ref lvi);
}
private static uint ListView_GetItemState(IntPtr hwndLV, int i, uint mask)
{
return (uint)SendMessage(hwndLV, LVM_GETITEMSTATE, i, (IntPtr)mask);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_REFLECT + WM_NOFITY)
{
var pnmhdr = (NMHDR)m.GetLParam(typeof(NMHDR));
if (pnmhdr.code == NM_CUSTOMDRAW)
{
var pnmlv = (NMLVCUSTOMDRAW)m.GetLParam(typeof(NMLVCUSTOMDRAW));
switch (pnmlv.nmcd.dwDrawStage)
{
case (int)CDDS.CDDS_PREPAINT:
m.Result = new IntPtr((int)CDRF.CDRF_NOTIFYITEMDRAW);
break;
case (int)CDDS.CDDS_ITEMPREPAINT:
m.Result = new IntPtr((int)(CDRF.CDRF_NOTIFYSUBITEMDRAW | CDRF.CDRF_NOTIFYPOSTPAINT));
break;
case (int)CDDS.CDDS_ITEMPOSTPAINT:
int nItem = (int)pnmlv.nmcd.dwItemSpec;
uint nItemState = ListView_GetItemState(m.HWnd, nItem, LVIS_CUT);
bool bCut = (nItemState & LVIS_CUT) == LVIS_CUT;
Rectangle itemRect = this.GetItemRect(nItem);
if (nItem != -1)
{
if (bCut)
{
using (Graphics gr = Graphics.FromHdc(pnmlv.nmcd.hdc))
{
Brush grayBrush = new SolidBrush(Color.FromArgb(120, 211, 211, 211));
gr.FillRectangle(grayBrush, itemRect);
}
}
}
break;
}
}
else if (pnmhdr.code == NM_DBLCLK)
{
var pnmlv = (NMLISTVIEW)m.GetLParam(typeof(NMLISTVIEW));
int nItem = pnmlv.iItem;
if (nItem != -1)
{
ListView_SetItemState(m.HWnd, nItem, LVIS_CUT, LVIS_CUT);
}
}
else if (pnmhdr.code == NM_RDBLCLK)
{
var pnmlv = (NMLISTVIEW)m.GetLParam(typeof(NMLISTVIEW));
int nItem = pnmlv.iItem;
if (nItem != -1)
{
ListView_SetItemState(m.HWnd, nItem, 0, LVIS_CUT);
}
}
return;
}
else
base.WndProc(ref m);
}
}