关于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;
新定义的继承类定义对象,并且用新的属性改变字体颜色就可以了。
|