Delphi TListview OwnerDraw SubItems - change default font (it's bold somehow after you Draw on the canvas)

一个人想着一个人 提交于 2019-11-27 07:59:32

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!