I have a code from here: Delphi: Canvas.FillRect in List View to paint rows (I use OwnerDraw).
Therefore I need to draw selections and mouse-hover effects. And to draw a normal column resizing effect...
I have a code to move items up and down:
procedure TForm1.ListViewDragDrop(Sender, Source: TObject; X,
Y: Integer);
var
DragItem, DropItem, CurrentItem, NextItem: TListItem;
begin
if Sender = Source then
with TListView(Sender) do
begin
DropItem := GetItemAt(X, Y);
CurrentItem := Selected;
while CurrentItem <> nil do
begin
NextItem := GetNextItem(CurrentItem, SdAll, [IsSelected]);
if DropItem = nil then DragItem := Items.Add
else
DragItem := Items.Insert(DropItem.Index);
DragItem.Assign(CurrentItem);
CurrentItem.Free;
CurrentItem := NextItem;
end;
end;
end;
procedure TForm1.ListViewDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := Sender = Update_ListBox;
end;
how to draw selections and mouse-hover effects on ListViewDrawItem + column resizing effect?
Thanks!!!
If you want to draw selections and in other ways respond to the current state of the control, you need to write additional code for this purpose, because we are owner-drawing the control. This means that we say to Windows, "hey, don't draw anything in the client area, I'll do that". Therefore, Windows draws nothing, not even selections, focus rectangles, and mouse-hover effects.
Fortunately, it is rather easy to implement this behaviour manually. Indeed, in the OnCustomDraw
event handler, you are given a State
parameter, which you can read. This is a set, and some of the possible elements include odSelected
, odHotLight
, and odFocused
.
Building upon our previous code, adding only a few new lines, we arrive at
procedure TForm1.ListView1DrawItem(Sender: TCustomListView; Item: TListItem;
Rect: TRect; State: TOwnerDrawState);
var
i: Integer;
x1, x2: integer;
r: TRect;
S: string;
const
DT_ALIGN: array[TAlignment] of integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
if SameText(Item.SubItems[1], 'done') then
begin
Sender.Canvas.Font.Color := clWhite;
Sender.Canvas.Brush.Color := clGreen;
end
else
if Odd(Item.Index) then
begin
Sender.Canvas.Font.Color := clBlack;
Sender.Canvas.Brush.Color := $F6F6F6;
end
else
begin
Sender.Canvas.Font.Color := clBlack;
Sender.Canvas.Brush.Color := clWhite;
end;
if odSelected in State then // NEW!
begin // NEW!
Sender.Canvas.Font.Color := clWhite; // NEW!
Sender.Canvas.Brush.Color := clNavy; // NEW!
end; // NEW!
Sender.Canvas.Brush.Style := bsSolid;
Sender.Canvas.FillRect(Rect);
x1 := 0;
x2 := 0;
r := Rect;
Sender.Canvas.Brush.Style := bsClear;
Sender.Canvas.Draw(3, r.Top + (r.Bottom - r.Top - bm.Height) div 2, bm);
for i := 0 to ListView1.Columns.Count - 1 do
begin
inc(x2, ListView1.Columns[i].Width);
r.Left := x1;
r.Right := x2;
if i = 0 then
begin
S := Item.Caption;
r.Left := bm.Width + 6;
end
else
S := Item.SubItems[i - 1];
DrawText(Sender.Canvas.Handle,
S,
length(S),
r,
DT_SINGLELINE or DT_ALIGN[ListView1.Columns[i].Alignment] or
DT_VCENTER or DT_END_ELLIPSIS);
x1 := x2;
end;
if odFocused in State then // NEW!
DrawFocusRect(Sender.Canvas.Handle, Rect); // NEW!
end;
Notice that the 'horse' line is selected and has keyboard focus.