【问题标题】:TTreeView custom draw of selected item选中项的TTreeView自定义绘制
【发布时间】:2013-07-08 20:05:03
【问题描述】:

我正在尝试为我的应用程序模拟 Outlook 2013 左窗格树视图菜单。我使用 CustomDraw 是因为我只想更改一些简单的字体和背景属性。

这就是我想要的:

但是,对于选定节点和热跟踪节点,我总是得到默认选定的图形。我没有 Windows 7 或 XP,无法查看这是正常行为还是与我的操作系统(Windows 8)有关。

这是我得到的:

这是我的代码:

procedure TMainForm.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  if Node.Level = 1 then
    Sender.Canvas.Font.Size := Sender.Canvas.Font.Size + 2;

  if cdsHot in State then
    Sender.Canvas.Brush.Color := $00F7E6CD
  else if (cdsSelected in State) or (cdsFocused in State) or
    (cdsChecked in State) then
    Sender.Canvas.Brush.Color := $00F2F2F2
  else
    Sender.Canvas.Brush.Color := $00DEDEDE;
  DefaultDraw := true;
end;

我怎样才能为选定和热门项目绘制不同颜色的背景?

【问题讨论】:

  • 我相信你必须取消主题控制才能使它工作。禁用应用程序的运行时主题,或者至少在树视图上使用空字符串调用 SetWindowTheme
  • 也许你可以从 VirtualStringTree 开始?
  • 其实我觉得我说的不对。文档特别提到您必须通过调用 SetWindowTheme 来禁用视觉样式的工具栏,但没有提及任何其他控件。 Link.
  • @SertacAkyuz,您应该发布答案,因为您基本上在 cmets 中解决了它,甚至没有看到它,删除了我的答案。
  • @Peter - 没问题,我可以不发布答案,请恢复您的答案。实际上,如果有人没有提出解释,我稍后会投票给你。如果 MS 的文件不完整或类似情况,我不会感到惊讶。

标签: delphi windows-8 treeview delphi-xe


【解决方案1】:

尝试以下方法:

type
  TTreeView = class(Vcl.ComCtrls.TTreeView)
  protected
    procedure CreateWnd; override;
  end;


uses uxtheme;

procedure TTreeView.CreateWnd;
begin
  inherited;
  SetWindowTheme(Handle, nil , nil);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin

   TreeView1.Font.Name := 'Segoe UI';
   TreeView1.HotTrack := True;
   TreeView1.Font.Size := TreeView1.Font.Size + 1;
   TreeView1.Color := $00DEDEDE;

end;

procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin

   if cdsFocused in State then begin
     Sender.Canvas.Brush.Color := $00F2F2F2;
     Sender.Canvas.Font.Color := clblack;
     Sender.Canvas.Font.Style := Sender.Canvas.Font.Style + [fsBold];
   end else if cdsHot in State then
    Sender.Canvas.Brush.Color := $00F7E6CD
   else
    Sender.Canvas.Brush.Color := $00DEDEDE;

end;

说明:

关于这方面的 Microsoft 文档非常模糊,我可以肯定地说,每当对项目(选择、热跟踪、取消选择等)执行操作( Node),发送特定消息,该消息通过参数标志包含节点的状态,最后在内部决定如何根据当前 Windows 主题直观地更新项目。

这就是为什么禁用 TreeView 组件的主题会删除默认选择矩形和主题颜色的可能原因。 Control state flags 的文档部分支持这一理论。

【讨论】:

  • 任何解释为什么必须禁用控件上的主题才能使着色起作用?
  • 因为主题化选择的项目基本上被屏蔽了。他的颜色确实被绘制了,但在实际的主题选择区域下。
  • 这不正确,但这也不是我要问的。不正确,因为这些颜色与 NMTVCUSTOMDRAW 结构的 clrText 和 clrTextBk 成员一起返回,供系统在绘制时使用。系统要么使用这些颜色,要么不使用,没有绘画结束。但无论如何,我要问的是你有没有关于禁用控件主题的 MS 参考?否则你观察到的行为也是我观察到的行为。
  • +1 因为我同意主题化覆盖自定义绘图。我喜欢代码,但答案更好..
  • 调用 SetWindowTheme 需要在 CreateWnd 中,以防重新创建窗口。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-17
  • 2018-10-11
  • 1970-01-01
  • 2017-04-09
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
相关资源
最近更新 更多