问题描述
我正在使用 OnAdvancedCustomDrawItem
事件从头开始自定义 TTreeView
绘图,我不知道如何呈现这些选择和我的主人背景中的热矩形正确的绘制项目?他们是Vista / 7风格,所以我不能简单地填充一些纯色的背景。
我试图在 cdPostPaint
,但是如果我在 cdPrePaint
阶段留下 DefaultDraw:= True
来绘制选择背景,则会发生完整的默认绘图,其中包括
程序TForm1.TreeView1AdvancedCustomDrawItem(发件人:TCustomTreeView;
节点:TTreeNode;状态:TCustomDrawState;舞台:TCustomDrawStage; var PaintImages,
DefaultDraw:Boolean);
begin
case
cdPreErase:
begin
DefaultDraw:= True;
结束
cdPostErase:
begin
DefaultDraw:= True;
结束
cdPrePaint:
begin
//我以为这将只绘制所选/热的背景,
//但是这将绘制整个项目,包括文本。
DefaultDraw:= True;
结束
cdPostPaint:
begin
DefaultDraw:= False;
//画我的所有者绘制文本
// .........
end;
结束
PaintImages:= False;
结束
这是我的解决方案(测试)。 >
请注意,TreeView必须具有 HotTrack:= True
可以正常绘制热门项目。
当主题未启用时,还必须附加绘图。
使用
UxTheme,
主题;
const
TreeExpanderSpacing = 6;
程序TForm1.DrawExpander(ACanvas:TCanvas; ATextRect:TRect; AExpanded:Boolean;
AHot:Boolean);
var
ExpanderRect:TRect;
图形:IGPGraphics;
积分:TGPPoint数组;
刷:IGPBrush;
笔:IGPPen;
ThemeData:HTHEME;
ElementPart:整数;
ElementState:Integer;
ExpanderSize:TSize;
UnthemedColor:TColor;
begin
如果ThemeServices.ThemesEnabled然后
开始
如果AHot然后
ElementPart:= TVP_HOTGLYPH
else
ElementPart:= TVP_GLYPH;
如果AExpanded然后
ElementState:= GLPS_OPENED
else
ElementState:= GLPS_CLOSED;
ThemeData:= OpenThemeData(TreeView1.Handle,VSCLASS_TREEVIEW);
GetThemePartSize(ThemeData,ACanvas.Handle,ElementPart,ElementState,nil,
TS_TRUE,ExpanderSize);
ExpenderRect.Left:= ATextRect.Left - TreeExpanderSpacing - ExpanderSize.cx;
ExpanderRect.Right:= ExpanderRect.Left + ExpanderSize.cx;
ExpanderRect.Top:= ATextRect.Top +(ATextRect.Bottom - ATextRect.Top - ExpanderSize.cy)div 2;
ExpanderRect.Bottom:= ExpanderRect.Top + ExpanderSize.cy;
DrawThemeBackground(ThemeData,ACanvas.Handle,ElementPart,ElementState,ExpanderRect,nil);
CloseThemeData(ThemeData);
end
else
begin
//没有主题的绘图扩展器
图形:= TGPGraphics.Create(ACanvas.Handle);
Graphics.SmoothingMode:= SmoothingModeHighQuality;
ExpanderRect:= ATextRect;
ExpanderRect.Right:= ATextRect.Left - TDPIAware.GetScaledSize(TreeExpanderSpacing96dpi);
ExpanderRect.Left:= ATextRect.Left - TDPIAware.GetScaledSize(TreeExpanderSpacing96dpi) -
TDPIAware.GetScaledSize(Max(TreeExpanderCollapsedWidth96dpi,TreeExpanderExpandedWidth96dpi));
如果ASelected然后
UnthemedColor:= ColorToRGB(clHighlightText)
else
如果AExpanded然后
UnthemedColor:= clBlack
else
UnthemedColor:= clGray;
SetLength(Points,3);
如果AExpanded然后
开始
点[0]:= TGPPoint.Create(ExpanderRect.Right,ExpanderRect.Top +
(ExpanderRect.Bottom - ExpanderRect.Top - TreeExpanderExpandedHeight96dpi)div 2);
Points [1]:= TGPPoint.Create(ExpanderRect.Right,ExpanderRect.Top +
(ExpanderRect.Bottom - ExpanderRect.Top + TreeExpanderExpandedHeight96dpi)div 2);
Points [2]:= TGPPoint.Create(ExpanderRect.Right - TreeExpanderExpandedWidth96dpi,
ExpanderRect.Top +(ExpanderRect.Bottom - ExpanderRect.Top +
TreeExpanderExpandedHeight96dpi)div 2);
画笔:= TGPSolidBrush.Create(TGPColor.CreateFromColorRef(UnthemedColor));
Graphics.FillPolygon(Brush,Points);
end
else
begin
Points [0]:= TGPPoint.Create(ExpanderRect.Right - TreeExpanderCollapsedWidth96dpi,
ExpanderRect.Top +(ExpanderRect.Bottom - ExpanderRect。顶部 -
TreeExpanderCollapsedHeight96dpi)div 2);
Points [1]:= TGPPoint.Create(ExpanderRect.Right,
ExpanderRect.Top +(ExpanderRect.Bottom - ExpanderRect.Top)div 2);
Points [2]:= TGPPoint.Create(ExpanderRect.Right - TreeExpanderCollapsedWidth96dpi,
ExpanderRect.Top +(ExpanderRect.Bottom - ExpanderRect.Top +
TreeExpanderCollapsedHeight96dpi)div 2);
笔:= TGPPen.Create(TGPColor.CreateFromColorRef(UnthemedColor));
Graphics.DrawPolygon(Pen,Points);
结束
结束
结束
程序TForm1.TreeView1AdvancedCustomDrawItem(发件人:TCustomTreeView;
节点:TTreeNode;状态:TCustomDrawState;舞台:TCustomDrawStage; var PaintImages,
DefaultDraw:Boolean);
var
NodeRect:TRect;
NodeTextRect:TRect;
文本:string;
ThemeData:HTHEME;
TreeItemState:Integer;
begin
如果Stage = cdPrePaint然后
begin
NodeRect:= Node.DisplayRect(False);
NodeTextRect:= Node.DisplayRect(True);
//绘制背景
if(cdsSelected in State)and Sender.Focused then
TreeItemState:= TREIS_SELECTED
else
if(cdsSelected in State)和(cdsHot在州)然后
TreeItemState:= TREIS_HOTSELECTED
else
如果cdsSelected在州然后
TreeItemState:= TREIS_SELECTEDNOTFOCUS
else
如果cdsHot在状态那么
TreeItemState:= TREIS_HOT
else
TreeItemState:= TREEITEMStateFiller0;
如果TreeItemState<> TREEITEMStateFiller0然后
begin
ThemeData:= OpenThemeData(Sender.Handle,VSCLASS_TREEVIEW);
DrawThemeBackground(ThemeData,Sender.Canvas.Handle,TVP_TREEITEM,TreeItemState,
NodeRect,nil);
CloseThemeData(ThemeData);
结束
//绘图扩展器
如果Node.HasChildren然后
DrawExpander(Sender.Canvas,NodeTextRect,Node.Expanded,cdsHot在状态);
//绘制主文本
SetBkMode(Sender.Canvas.Handle,TRANSPARENT);
SetTextColor(Sender.Canvas.Handle,clBlue);
文本:= Node.Text;
Sender.Canvas.TextRect(NodeTextRect,Text,
[tfVerticalCenter,tfSingleLine,tfEndEllipsis,tfLeft]);
//某些扩展图...
end;
PaintImages:= False;
DefaultDraw:= False;
结束
I'm doing custom TTreeView
drawing from scratch using OnAdvancedCustomDrawItem
event, and I wonder how to render these selection and hot rectangles correctly in the background of my owner-draw items? They are Vista/7 styled so I cannot simply fill the background in some solid color.
I tried to draw my items at cdPostPaint
stage, but if I leave DefaultDraw := True
atcdPrePaint
stage to draw selection background, the complete default drawing occurs, including text of items.
procedure TForm1.TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage; var PaintImages,
DefaultDraw: Boolean);
begin
case Stage of
cdPreErase:
begin
DefaultDraw := True;
end;
cdPostErase:
begin
DefaultDraw := True;
end;
cdPrePaint:
begin
// I thought this will paint only the selected/hot backgrounds,
// however this will paint whole item, including text.
DefaultDraw := True;
end;
cdPostPaint:
begin
DefaultDraw := False;
// painting my owner-draw text
// .........
end;
end;
PaintImages := False;
end;
Here is my solution (tested).
Note the TreeView must have HotTrack := True
to draw hot items normally.
There also must be additional drawing when themes not enabled.
uses
UxTheme,
Themes;
const
TreeExpanderSpacing = 6;
procedure TForm1.DrawExpander(ACanvas: TCanvas; ATextRect: TRect; AExpanded: Boolean;
AHot: Boolean);
var
ExpanderRect: TRect;
Graphics: IGPGraphics;
Points: array of TGPPoint;
Brush: IGPBrush;
Pen: IGPPen;
ThemeData: HTHEME;
ElementPart: Integer;
ElementState: Integer;
ExpanderSize: TSize;
UnthemedColor: TColor;
begin
if ThemeServices.ThemesEnabled then
begin
if AHot then
ElementPart := TVP_HOTGLYPH
else
ElementPart := TVP_GLYPH;
if AExpanded then
ElementState := GLPS_OPENED
else
ElementState := GLPS_CLOSED;
ThemeData := OpenThemeData(TreeView1.Handle, VSCLASS_TREEVIEW);
GetThemePartSize(ThemeData, ACanvas.Handle, ElementPart, ElementState, nil,
TS_TRUE, ExpanderSize);
ExpanderRect.Left := ATextRect.Left - TreeExpanderSpacing - ExpanderSize.cx;
ExpanderRect.Right := ExpanderRect.Left + ExpanderSize.cx;
ExpanderRect.Top := ATextRect.Top + (ATextRect.Bottom - ATextRect.Top - ExpanderSize.cy) div 2;
ExpanderRect.Bottom := ExpanderRect.Top + ExpanderSize.cy;
DrawThemeBackground(ThemeData, ACanvas.Handle, ElementPart, ElementState, ExpanderRect, nil);
CloseThemeData(ThemeData);
end
else
begin
// Drawing expander without themes enabled
Graphics := TGPGraphics.Create(ACanvas.Handle);
Graphics.SmoothingMode := SmoothingModeHighQuality;
ExpanderRect := ATextRect;
ExpanderRect.Right := ATextRect.Left - TDPIAware.GetScaledSize(TreeExpanderSpacing96dpi);
ExpanderRect.Left := ATextRect.Left - TDPIAware.GetScaledSize(TreeExpanderSpacing96dpi) -
TDPIAware.GetScaledSize(Max(TreeExpanderCollapsedWidth96dpi, TreeExpanderExpandedWidth96dpi));
if ASelected then
UnthemedColor := ColorToRGB(clHighlightText)
else
if AExpanded then
UnthemedColor := clBlack
else
UnthemedColor := clGray;
SetLength(Points, 3);
if AExpanded then
begin
Points[0] := TGPPoint.Create(ExpanderRect.Right, ExpanderRect.Top +
(ExpanderRect.Bottom - ExpanderRect.Top - TreeExpanderExpandedHeight96dpi) div 2);
Points[1] := TGPPoint.Create(ExpanderRect.Right, ExpanderRect.Top +
(ExpanderRect.Bottom - ExpanderRect.Top + TreeExpanderExpandedHeight96dpi) div 2);
Points[2] := TGPPoint.Create(ExpanderRect.Right - TreeExpanderExpandedWidth96dpi,
ExpanderRect.Top + (ExpanderRect.Bottom - ExpanderRect.Top +
TreeExpanderExpandedHeight96dpi) div 2);
Brush := TGPSolidBrush.Create(TGPColor.CreateFromColorRef(UnthemedColor));
Graphics.FillPolygon(Brush, Points);
end
else
begin
Points[0] := TGPPoint.Create(ExpanderRect.Right - TreeExpanderCollapsedWidth96dpi,
ExpanderRect.Top + (ExpanderRect.Bottom - ExpanderRect.Top -
TreeExpanderCollapsedHeight96dpi) div 2);
Points[1] := TGPPoint.Create(ExpanderRect.Right,
ExpanderRect.Top + (ExpanderRect.Bottom - ExpanderRect.Top) div 2);
Points[2] := TGPPoint.Create(ExpanderRect.Right - TreeExpanderCollapsedWidth96dpi,
ExpanderRect.Top + (ExpanderRect.Bottom - ExpanderRect.Top +
TreeExpanderCollapsedHeight96dpi) div 2);
Pen := TGPPen.Create(TGPColor.CreateFromColorRef(UnthemedColor));
Graphics.DrawPolygon(Pen, Points);
end;
end;
end;
procedure TForm1.TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage; var PaintImages,
DefaultDraw: Boolean);
var
NodeRect: TRect;
NodeTextRect: TRect;
Text: string;
ThemeData: HTHEME;
TreeItemState: Integer;
begin
if Stage = cdPrePaint then
begin
NodeRect := Node.DisplayRect(False);
NodeTextRect := Node.DisplayRect(True);
// Drawing background
if (cdsSelected in State) and Sender.Focused then
TreeItemState := TREIS_SELECTED
else
if (cdsSelected in State) and (cdsHot in State) then
TreeItemState := TREIS_HOTSELECTED
else
if cdsSelected in State then
TreeItemState := TREIS_SELECTEDNOTFOCUS
else
if cdsHot in State then
TreeItemState := TREIS_HOT
else
TreeItemState := TREEITEMStateFiller0;
if TreeItemState <> TREEITEMStateFiller0 then
begin
ThemeData := OpenThemeData(Sender.Handle, VSCLASS_TREEVIEW);
DrawThemeBackground(ThemeData, Sender.Canvas.Handle, TVP_TREEITEM, TreeItemState,
NodeRect, nil);
CloseThemeData(ThemeData);
end;
// Drawing expander
if Node.HasChildren then
DrawExpander(Sender.Canvas, NodeTextRect, Node.Expanded, cdsHot in State);
// Drawing main text
SetBkMode(Sender.Canvas.Handle, TRANSPARENT);
SetTextColor(Sender.Canvas.Handle, clBlue);
Text := Node.Text;
Sender.Canvas.TextRect(NodeTextRect, Text,
[tfVerticalCenter, tfSingleLine, tfEndEllipsis, tfLeft]);
// Some extended drawing...
end;
PaintImages := False;
DefaultDraw := False;
end;
这篇关于在AdvancedCustomDrawItem中如何绘制TTreeView的样式选择矩形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!