问题
If you use ownerdraw with a TListView, the subitems are all BOLD font style by default somehow, even if the listview font.style is set to [], for all the SubItems following a custom drawn one.
A workaround I found is forcing the Style set in the CustomDrawSubItem event:
ListView2.Canvas.Font.Style := [fsItalic];
ListView2.Canvas.Font.Style := [];
(a simple call with [] won't work unless the default style is set to something other than [], because the SetStyle call doesn't think the style has changed)
This is however an ugly fix which involves extra processing time. Is there a better solution?
Demo project: http://www.mediafire.com/?v8bsdpvpfqy47vn
回答1:
I haven't encountered the exact situation you describe, but I have encountered a similar issue. When I use an owner-drawn TListView
with an OnAdvancedCustomDrawSubItem
event assigned to change the Canvas.Font
on a per-subitem basis, I find that after I have changed the Sender.Canvas.Font
for one subitem, subsequent subitems get drawn with the wrong settings even if I change the Sender.Canvas.Font
for them. My workaround is to manually call the Sender.Canvas.Font.OnChange
event handler at the end of my OnAdvancedCustomDrawSubItem
event handler. That signals TListView
to report back CDRF_NEWFONT
to Windows, then everything gets drawn correctly. It is as if the Sender.Canvas.Font.OnChange
event is not hooked up correctly while TListView
is being owner-drawn, so it does not detect font changes and thus does not report back to Windows correctly.
回答2:
I agree with jachguate's comment with that there seems to be an issue with the VCL control; a possibe design issue with TCustomListView.CNNotify
. But it's not easy to follow the logic there.
One solution is to force a change on the canvas of the control when DefaultDraw is true, so that the VCL creates and selects the control's font again to the passed DC before the custom drawing notification returns. Example:
procedure TForm1.LVCustomDrawSubItem(Sender: TCustomListView; Item: TListItem;
SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean);
Var R: TRect;
bmp: TBitmap;
x: Integer;
begin
DefaultDraw := True;
if SubItem = 1 then begin
DefaultDraw := False;
...
...
Sender.Canvas.Draw(R.Left - 2, R.Top, Bmp);
Bmp.Free;
end;
end;
if DefaultDraw then
Sender.Canvas.Brush.Color := ColorToRGB(clWindow); // <--
end;
The way I would prefer is to avoid using the control's canvas, if at all possible. You can use a temporary DC for your case, this also avoids the black background problem mentioned in the comments to the question.
uses
commctrl;
...
procedure TForm1.LVCustomDrawSubItem(Sender: TCustomListView; Item: TListItem;
SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean);
Var R: TRect;
bmp: TBitmap;
x: Integer;
DC: HDC;
begin
DefaultDraw := True;
if SubItem = 1 then begin
DefaultDraw := False;
...
...
DC := GetDC(Sender.Handle);
ImageList_Draw(TypeImages.Handle, 0, DC, R.Left - 2, R.Top, ILD_NORMAL);
ReleaseDC(Sender.Handle, DC);
Bmp.Free;
end;
end;
end;
来源:https://stackoverflow.com/questions/13485761/delphi-tlistview-ownerdraw-subitems-change-default-font-its-bold-somehow-aft