//---------------------------------------------------------------------------
//in
source...
#define
LV_EX_CHECKED 0x2000;
#define
LVS_EX_CHECKBOXES 0x4
#define
LVM_SETEXTENDEDLISTVIEWSTYLE (LVM_FIRST + 54)
__fastcall TForm1::TForm1(TComponent*
Owner)
: TForm(Owner)
{
LVCanvas
= new TCanvas();
LVCanvas->Font
= ListView1->Font;
ListView1->ReadOnly
= true;
//These
two lines make the ListView owner-drawn
//(only possible in vsReport ViewStyle)
LONG
dwStyle = GetWindowLong(ListView1->Handle, GWL_STYLE);
SetWindowLong(ListView1->Handle,
GWL_STYLE, dwStyle | LVS_OWNERDRAWFIXED);
//add
the checkbox style
ListView1->Perform(LVM_SETEXTENDEDLISTVIEWSTYLE,
0, (LPARAM)LVS_EX_CHECKBOXES);
//check
all checkboxes
for
(int index = 0; index < ListView1->Items->Count; index++)
{
LONG state = LV_EX_CHECKED;
ListView_SetItemState(ListView1->Handle, index, state, LVIS_STATEIMAGEMASK);
}
}
//---------------------------------------------------------------------------
//This
is the function that the WM_DRAWITEM message maps to.
//The
LParam member is in the form of a DRAWITEMSTRUCT structure
void __fastcall
TForm1::DrawListView(TMessage &Message)
{
LPDRAWITEMSTRUCT
lpdis = (DRAWITEMSTRUCT *)Message.LParam;
//the
WM_DRAWITEM may be shared (for example, BitBtns)
//only handle the drawing if the message corresponds
//to the target ListView
if
(lpdis->hwndItem != ListView1->Handle)
{
TForm::Dispatch(&Message);
return;
}
int
Index = lpdis->itemID;
UINT
ItemState = lpdis->itemState;
LVCanvas->Handle
= lpdis->hDC;
TRect
DrawRect = lpdis->rcItem;
RECT
ItemRect;
ListView_GetItemRect(ListView1->Handle,
Index, &ItemRect, LVIR_SELECTBOUNDS);
LONG
CBDrawState = DFCS_BUTTONCHECK;
RECT
CBRect;
CBRect.left
= 0;
CBRect.top
= DrawRect.Top;
CBRect.right
= check_box_width;
CBRect.bottom
= DrawRect.Bottom;
BeginPaint(ListView1->Handle,
&ps);
//determine
if the checkbox is checked
LONG
state = SendMessage(ListView1->Handle, LVM_GETITEMSTATE,
Index, LVIS_STATEIMAGEMASK);
bool
checked = state & LV_EX_CHECKED;
if
(checked) //flag the "checked" drawing style
{
CBDrawState = CBDrawState | DFCS_CHECKED;
LVCanvas->Font->Color = ListView1->Font->Color;
LVCanvas->Brush->Color = ListView1->Color;
LVCanvas->FillRect((TRect)ItemRect);
}
else//gray
the item
{
LVCanvas->Font->Color = clGrayText;
LVCanvas->Brush->Color = ListView1->Color;
LVCanvas->FillRect((TRect)ItemRect);
}
if
(checked && (ItemState & ODS_SELECTED)) //if
selected
{
LVCanvas->Font->Color = clHighlightText;
LVCanvas->Brush->Color = clHighlight;
LVCanvas->FillRect((TRect)ItemRect);
}
//draw
the checkbox
DrawFrameControl(LVCanvas->Handle,
&CBRect, DFC_BUTTON, CBDrawState);
//Draw
the corresponding icon
RECT
IconRect;
ListView_GetItemRect(ListView1->Handle,
Index, &IconRect, LVIR_ICON);
int
IconIndex = ListView1->Items->Item[Index]->ImageIndex;
ImageList1->Draw(LVCanvas,
IconRect.left, IconRect.top, IconIndex);
DrawRect.Left
= IconRect.right + 2;
LVCanvas->Brush->Style
= bsClear;
DrawRect.Right
= ListView1->Columns->Items[0]->Width;
LVCanvas->TextRect(DrawRect,DrawRect.Left,
DrawRect.Top,
ListView1->Items->Item[Index]->Caption);
//draw
the sub-items
if
(checked)
{
LVCanvas->Font->Color = ListView1->Font->Color;
LVCanvas->Brush->Color = ListView1->Color;
}
DrawRect.Left
= IconRect.left - check_box_width + 5;
for
(int col = 0; col < ListView1->Items->Item[Index]->SubItems->Count;
col++)
{
DrawRect.Left = DrawRect.Left + ListView1->Columns->Items[col]->Width +
1;
DrawRect.Right = DrawRect.Left + ListView1->Columns->Items[col + 1]->Width;
AnsiString TextToDraw;
TextToDraw = ListView1->Items->Item[Index]->SubItems->Strings[col];
LVCanvas->TextRect(DrawRect, DrawRect.Left, DrawRect.Top, TextToDraw);
}
EndPaint(ListView1->Handle,
&ps);
}
//---------------------------------------------------------------------------
//this
OnMouseDown event handler uses the
//ListView_HitTest
macro to determine if/which
//item
in a ListView is clicked. It then toggles
//the
state of the corresponding checkbox whose changes
//are
reflected by the DrawListView message handler
void __fastcall
TForm1::ListView1MouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int
X, int Y)
{
LV_HITTESTINFO
lvhti;
lvhti.pt.x
= X;
lvhti.pt.y
= Y;
int
index = ListView_HitTest(ListView1->Handle, &lvhti);
//if
(index != -1 && X < 20) for only a checkbox click
if
(index != -1)
{
LONG state = SendMessage(ListView1->Handle, LVM_GETITEMSTATE,
index, LVIS_STATEIMAGEMASK);
bool checked = state & LV_EX_CHECKED;
if (checked) state = 0x1000; //uncheck
else state = LV_EX_CHECKED; //check
ListView_SetItemState(ListView1->Handle, index,
state, LVIS_STATEIMAGEMASK);
}
}
|