如何在AdvancedCustomDrawItem期间绘制TTreeView的样式选择矩形?

2023-11-23

我是做定制的TTreeView使用从头开始绘制OnAdvancedCustomDrawItem事件,我想知道如何在我的所有者绘制项目的背景中正确渲染这些选择和热矩形?它们是 Vista/7 风格的,所以我不能简单地用纯色填充背景。

enter image description here

我尝试在以下位置绘制我的物品cdPostPaint舞台,但如果我离开DefaultDraw := True atcdPrePaint阶段绘制选择背景,发生完整的默认绘制,包括项目的文本。

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;

这是我的解决方案(经过测试)。

注意 TreeView 必须有HotTrack := True正常绘制热门项目。

当主题未启用时,还必须有额外的绘图。

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;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在AdvancedCustomDrawItem期间绘制TTreeView的样式选择矩形? 的相关文章

  • 将 TPopupMenu 与窗体的右侧对齐?

    TPopupMenu 如何与窗体的右侧对齐 问题是 在调用之前似乎没有办法获取弹出菜单的宽度Popup X Y Integer 我正在尝试获得与 Chrome 中的系统菜单类似的行为 你也可以只设置Alignment http docwik
  • WPF 中的自动展开树视图

    有没有办法在 WPF 中自动展开树视图中的所有节点 我搜索了 甚至没有在 treeview 属性中找到展开功能 Thanks 您可以设置 ItemContainerStyle 并使用 IsExpanded 属性
  • Delphi LZMA减压样本

    我发现在this https stackoverflow com questions 4344976 lzma or 7zip in delphi的线程链接delphi压缩包 https github com ccy delphi zip具
  • 可以在delphi数据集中创建一个假数据字段吗?

    我想在 DataSet 不是 ClientDataSet 中创建一个 假 数据字段 该字段不应存储在数据库中 它不是计算字段 应允许用户输入输入数据 该字段具有业务逻辑含义 因此用户更新其值后应该更新其他字段 使用 OnFieldChang
  • 作为属性的类引用

    谷歌对于这类搜索毫无用处 因为你会得到数亿个结果 其中没有一个与特定问题相关 问题很简单 Delphi 中是否可以有类引用属性 如果是这样 怎么办 这是我尝试过的 type TMyObject class end TMyObjectClas
  • delphi中生成随机数

    我想在delphi中创建一个随机数并将其分配给文件作为文件名 我设法做到了这一点 但是当我单击按钮生成数字时 它总是以 0 开头 知道如何修复它 procedure TForm1 Button1Click Sender TObject va
  • 在 Delphi 7 中使用 TScreen

    我的 Delphi 7 应用程序显示 Screen DesktopWidth Screen DesktopHeight Screen Monitors 0 Width Screen Monitors 0 Height 并且 如果选择了第二台
  • Delphi 2010:如何将 UTF8 编码的 PAnsiChar 转换为 UnicodeString?

    情况 我有一个外部 DLL 它使用 UTF 8 作为其内部字符串格式 接口函数都使用 PAnsiChar 来传递字符串 我的应用程序的其余部分使用 Delphi 的本机string类型 由于我正在使用 Delphi 2010 这将映射到Un
  • 在主表单之前显示登录表单

    我在表单之间导航时遇到问题 我使用 Delphi XE5 创建了一个 Android Firemonkey 移动应用程序 我目前有一个登录表单和主表单 现在我想要有关如何处理登录表单以显示在主表单之前的建议 在 项目选项 中的表单下 选择要
  • 如何正确实现TBitmap的扫描线访问?

    我正在尝试根据以下方式访问位图的扫描线关于内河码头的文章 http edn embarcadero com article 29173 使用像这样的扫描线 for y 0 to n do begin line bitmap scanline
  • 如何使用 jQuery 和“长轮询”通过 Indy HTTP 服务器动态更新 HTML 页面?

    我读过这篇文章使用 JavaScript 和 jQuery 的简单长轮询示例 http techoctave com c7 posts 60 simple long polling example with javascript and j
  • Indy FTP 传输类型

    我正在使用 IdFTP Indy 10 组件从远程位置下载一些文件 zip 和 txt 在获取每个文件之前 我将 TransferType 设置为二进制 IdFTP TransferType ftBinary IdFTP Get ASour
  • Winform 没有.NET 框架?

    我必须创建一些表单并将其作为直接 EXE 提供 而不是安装程序 它安装 NET 框架 最终用户对此不满意 他们想要可以直接打开和工作的东西 我知道它可以作为网络完成 但我正在寻找 winforms 吗 请建议哪种工具 技术可以处理这个问题
  • 从单个应用程序中的多个线程调用 dll 函数是否安全?

    我正在 Delphi 2009 中编写一个服务器应用程序 它实现了多种类型的身份验证 每种身份验证方法都存储在单独的 dll 中 第一次使用身份验证方法时 会加载适当的 dll 仅当应用程序关闭时 DLL 才会被释放 在服务器线程 连接 之
  • 在 jsTree 上下文菜单中创建自定义项目

    我在 asp net mvc3 中使用 jsTree 和 contextmenu 创建一个树视图 div ul li a href class usr Model Name a Html Partial Childrens Model li
  • WinForms TreeView - 如何手动“突出显示”节点(就像被单击一样)

    我需要知道如何让以编程方式选择的节点以图形方式处于 选定 状态 就像用户单击它一样 SelectedNode 仅使这一节点在内部被选中 非常感谢 它没有显示为突出显示的原因是由于树视图没有焦点 这是我的测试表单上的按钮单击事件 TreeVi
  • 如何允许表单接受文件删除而不处理 Windows 消息?

    在 Delphi XE 中 我可以允许我的表单接受文件 拖放 但不必处理裸窗口消息吗 您不需要处理消息来实现这一点 你只需要实施IDropTarget并打电话RegisterDragDrop RevokeDragDrop 这真的非常非常简单
  • 使用 Javascript 获取 Mobile Safari 中选定的文本

    因此 我正在开发一个小书签 对于我来说 使用 循环 获取用户选择的内容是理想的选择 window getSelection 和 document getSelection 都是我可以调用的函数 但是它们始终返回空字符串 我相信问题在于 当您
  • 在 Delphi XE 中将类作为过程的参数传递

    我需要做的是这样的 procedure A type of form var form TForm begin form type of form Create application form showmodal freeandnil f
  • 双击 TreeNode 复选框上的行为

    我有一个TreeView填充有TreeNodes有图标和复选框 我一直在尝试禁用其中一些人的检查 取消检查能力 从而丢弃事件中的事件BerforeCheck方法 这工作正常 直到我双击复选框 复选框的图像与其真实状态相反 如果状态为Chec

随机推荐