分享

关于TListView控件,ondrawitem修改字体颜色导致gdi泄漏的解决办法

 quasiceo 2013-12-26

关于TListView控件,ondrawitem修改字体颜色导致gdi泄漏的解决办法

问题的提出:根据listview里的文字不同内容,显示不用的颜色。
同样的问题还会出现的TTreeview和TToolBar, delphi5,delphi6如果delphi7,delphi2005也发现有此问题,都可以用下列方法解决

//==============================================================================
//本实例演示
//关于TListView控件,ondrawitem修改字体颜色导致gdi泄漏的解决办法
//作者:cactus123456@hotmail.com
//日期:2005.12.31
//版本:1.0
//==============================================================================

procedure TForm1.ListView1DrawItem(Sender: TCustomListView;
  Item: TListItem; Rect: TRect; State: TOwnerDrawState);
begin
   case PDatainfo(item.Data).State of
      fsbook     : Sender.Canvas.Font.Color := clred;
      fsauth     : Sender.Canvas.Font.Color := $00404080;
   else     
     Sender.Canvas.Font.Color := clSilver;
   end;
end;

在这个事件里可以修改listview控件里每行或个每个元素的字体颜色,但是因为delphi原代码的bug,导致每次创建和释放Tlistview创建的对象时,都会导致1个gdi泄漏。

解决此问题有2种办法,一个是修改原文件代码,重新编译,替换掉原来的文件,另一种办法就是
利用继承机制,修改父类的bug,特别适用于不能修改源代码的情况。

方法一:
首先找到ComCtrls.pas文件(参考目录:Borland\Delphi6\Source\Vcl)备份,然后新建工程文件,拷贝并引用该单元ComCtrls.pas,修改代码,编译,将生成的ComCtrls.dcu拷贝到lib目录,覆盖掉原来的文件(参考目录:Borland\Delphi6\Lib),覆盖以前,同样强烈建议备份。


源代码:
> >with PNMLVCustomDraw(NMHdr)^ do
> >begin
> >  clrText := ColorToRGB(FCanvas.Font.Color);
> >  clrTextBk := ColorToRGB(FCanvas.Brush.Color);
> >  if GetObject(FCanvas.Font.Handle, SizeOf(LogFont), @LogFont) <> 0
> >then
> >  begin
> >    FCanvas.Handle := 0;  // disconnect from hdc
> >    // don't delete the stock font
> >    SelectObject(hdc, CreateFontIndirect(LogFont));
> >    Result := Result or CDRF_NEWFONT;
> >  end;
> >end;
//经验证是CreateFontIndirect(LogFont)这一句导致gdi泄漏

修改为:
> >with PNMLVCustomDraw(NMHdr)^ do
> >begin
> >  clrText := ColorToRGB(FCanvas.Font.Color);
> >  clrTextBk := ColorToRGB(FCanvas.Brush.Color);
> >  SelectObject(hdc, FCanvas.Font.Handle);
> >  Result := Result or CDRF_NEWFONT;
> >end;


方法二

定义一个继承类,重新写一个修改字体颜色的属性,重写消息
type
  TMyListView = class(TListView)
  private
    FItemFontColor : TColor;
    procedure CNNOTIFY(var Message : TWMNotify); message CN_NOTIFY;
  public
    property ItemFontColor : TColor read FItemFontColor write FItemFontColor;
  end;

procedure TMyListView.CNNotify(var Message: TWMNotify);
begin
  inherited;
  With Message do
  begin
    if NMHdr.code = NM_CUSTOMDRAW then
      if (pNMLVCUSTOMDRAW(NMHdr).nmcd.dwDrawStage and CDDS_ITEM) <> 0 then
        if pNMLVCUSTOMDRAW(NMHdr).nmcd.dwDrawStage or CDDS_ITEMPREPAINT <> 0 then
        begin
          Canvas.Font.OnChange := nil;
          Canvas.Brush.OnChange := nil;
          with PNMLVCustomDraw(NMHdr)^ do
          begin
            clrText := ColorToRGB(FItemFontColor);
            clrTextBk := ColorToRGB(Canvas.Brush.Color);
            SelectObject(PNMCustomDraw(NMHdr).hdc, Canvas.Font.Handle);
            Result := Result or CDRF_NEWFONT;
          end;
        end;
  end;

end;

新定义的继承类定义对象,并且用新的属性改变字体颜色就可以了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多