在AdvancedCustomDrawItem中如何绘制TTreeView的样式选择矩形? [英] How to draw TTreeView's styled selection rectangle during AdvancedCustomDrawItem?

查看:753
本文介绍了在AdvancedCustomDrawItem中如何绘制TTreeView的样式选择矩形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 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的样式选择矩形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆