【问题标题】:Overlaid images with TVirtualStringTree.OnGetImageIndex使用 TVirtualStringTree.OnGetImageIndex 覆盖图像
【发布时间】:2016-08-22 22:02:02
【问题描述】:

我想在vtTest 组件中显示来自ImageList1 的图像作为叠加层。

我在 Internet 和 SO 中找到了许多资源 - 例如 this - 但我无法让它们都正常工作。

我确定我错过了一些非常微不足道的东西,但我不知道它可能是什么。


我得到什么:      我想要什么:


这是包含显示我的问题的基本示例的表单。

Unit1.pas

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.ImgList;

type
  PMyVtTestData = ^TMyVtTestData;
  TMyVtTestData = record
    isLocked: Boolean;
  end;

  TForm1 = class(TForm)
    vtTest: TVirtualStringTree;
    ImageList1: TImageList;
    procedure FormCreate(Sender: TObject);
    procedure vtTestGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean;
      var ImageIndex: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i, j, m: Integer;
  Node, Node1, Node2: PVirtualNode;

  procedure SetCustomNodeDataValue(const Node: PVirtualNode; const Value: Boolean = False);
  var
    Data: PMyVtTestData;
  begin
    Data := vtTest.GetNodeData(Node);
    Data^.isLocked := Value;
  end;
begin
  vtTest.NodeDataSize := SizeOf(TMyVtTestData);

  //initialize some node
  //every TMyVtTestData.isLocked = False, except the 3rd TMyVtTestData.isLocked which is True
  Randomize;
  for i := 0 to Random(3)+3 do begin
    Node := vtTest.AddChild(nil);
    SetCustomNodeDataValue(Node, i = 2);
    for j := 0 to Random(3)+2 do begin
      Node1 := vtTest.AddChild(Node);
      SetCustomNodeDataValue(Node1);
      for m := 0 to Random(5) do begin
        Node2 := vtTest.AddChild(Node1);
        SetCustomNodeDataValue(Node2);
      end;
    end;
  end;
end;

procedure TForm1.vtTestGetImageIndex(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: Boolean; var ImageIndex: Integer);
var
  Data: PMyVtTestData;
begin

  if Node = nil then
    Exit;

  case Column of
    0: begin
      if Kind in [ikNormal, ikSelected] then
        ImageIndex := 0
      else if Kind = ikOverlay then begin
        Data := Sender.GetNodeData(Node);
        if Data^.isLocked then
          ImageIndex := 1;
      end;
    end;

  end;
end;

end.

Unit1.dfm

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 300
  ClientWidth = 313
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  DesignSize = (
    313
    300)
  PixelsPerInch = 96
  TextHeight = 13
  object vtTest: TVirtualStringTree
    Left = 8
    Top = 8
    Width = 298
    Height = 284
    Anchors = [akLeft, akTop, akRight, akBottom]
    Header.AutoSizeIndex = -1
    Header.Font.Charset = DEFAULT_CHARSET
    Header.Font.Color = clWindowText
    Header.Font.Height = -11
    Header.Font.Name = 'Tahoma'
    Header.Font.Style = []
    Header.Images = ImageList1
    Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible]
    Images = ImageList1
    TabOrder = 0
    OnGetImageIndex = vtTestGetImageIndex
    Columns = <
      item
        Position = 0
        Width = 200
        WideText = 'column'
      end>
  end
  object ImageList1: TImageList
    Left = 256
    Top = 240
    Bitmap = {
      494C010102000500040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
      0000000000003600000028000000400000001000000001002000000000000010
      0000000000000000000000000000000000000000000000000000000000000000
      0000868686003535350000000000000000000000000000000000939393005757
      5700000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000000000000000000000000000D9D9
      D9000505050000000000B1B1B1000000000000000000FCFCFC00222222000000
      0000A2A2A2000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000000000000000000000000000CCCC
      CC00353535007D7D7D002525250066666600939393001E1E1E00646464003434
      340085858500000000000000000000000000000000000000000000000000140C
      EB00B1AEF900FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B1AE
      F900140CEB000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000006E6E6E0000000000000000002E2E2E00000000000000
      0000000000000000000000000000000000000000000000000000140CEB000000
      00000300EA00B9B6F900FFFFFF00FFFFFF00FFFFFF00FFFFFF00B9B6F9000300
      EA0000000000140CEB0000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000007171
      7100000000002F2F2F0015151500D0D0D000F0F0F00031313100252525002121
      21005F5F5F000000000000000000000000000000000000000000B1AEF9000300
      EA002018EC00160DEC00B9B6F900FFFFFF00FFFFFF00B9B6F900160DEC002018
      EC000300EA00B1AEF90000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000000000000000000000000000BFBF
      BF00000000002222220000000000000000000000000000000000666666000000
      0000979797000000000000000000000000000000000000000000FFFFFF00B9B6
      F900160DEC002018EC000300EA00B1AEF900B1AEF9000300EA002018EC00160D
      EC00B9B6F900FFFFFF0000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000096969600B9B9B900000000007676760048484800D8D8D800EEEEEE006565
      6500F8F8F8000000000000000000000000000000000000000000FFFFFF00FFFF
      FF00B9B6F9000300EA0000000000140CEB00140CEB00000000000300EA00B9B6
      F900FFFFFF00FFFFFF0000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000E9E9E900313131000000000010101000000000009F9F9F000000
      0000000000000000000000000000000000000000000000000000FFFFFF00FFFF
      FF00FFFFFF00B1AEF900140CEB000000000000000000140CEB00B1AEF900FFFF
      FF00FFFFFF00FFFFFF0000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000001919190000000000353535007272720000000000000000009999
      9900000000000000000000000000000000000000000000000000FFFFFF00FFFF
      FF00FFFFFF00B1AEF900140CEB000000000000000000140CEB00B1AEF900FFFF
      FF00FFFFFF00FFFFFF0000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      00009A9A9A003B3B3B00000000004F4F4F0000000000B3B3B300C3C3C3004040
      4000000000000000000000000000000000000000000000000000FFFFFF00FFFF
      FF00B9B6F9000300EA0000000000140CEB00140CEB00000000000300EA00B9B6
      F900FFFFFF00FFFFFF0000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      00000D0D0D0062626200000000006F6F6F0000000000E5E5E500000000000000
      0000ADADAD000000000000000000000000000000000000000000FFFFFF00B9B6
      F900160DEC002018EC000300EA00B1AEF900B1AEF9000300EA002018EC00160D
      EC00B9B6F900FFFFFF0000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000000000000000000000000000E2E2
      E2000202020001010100555555000A0A0A000000000033333300444444000000
      0000848484000000000000000000000000000000000000000000B1AEF9000300
      EA002018EC00160DEC00B9B6F900FFFFFF00FFFFFF00B9B6F900160DEC002018
      EC000300EA00B1AEF90000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000000000000000000000000000DEDE
      DE00040404000000000000000000000000000000000000000000000000000000
      00007E7E7E000000000000000000000000000000000000000000140CEB000000
      00000300EA00B9B6F900FFFFFF00FFFFFF00FFFFFF00FFFFFF00B9B6F9000300
      EA0000000000140CEB0000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      00003C3C3C000000000000000000000000000000000000000000000000000000
      0000BDBDBD00000000000000000000000000000000000000000000000000140C
      EB00B1AEF900FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B1AE
      F900140CEB000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000E1E1E1000E0E0E0000000000000000000000000000000000000000007676
      7600000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000F5F5F5008787870042424200363636005C5C5C00C3C3C3000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000424D3E000000000000003E000000
      2800000040000000100000000100010000000000800000000000000000000000
      000000000000000000000000FFFFFF00F3CFFFFF00000000E187FFFF00000000
      E007E00700000000FC3FD00B00000000E007C00300000000E3C7C00300000000
      F207C24300000000F81FC18300000000F80FC18300000000F20FC24300000000
      F227C00300000000E007C00300000000E007D00B00000000F007E00700000000
      F00FFFFF00000000F81FFFFF0000000000000000000000000000000000000000
      000000000000}
  end
end

提示

  • VirtualTrees 在 Delphi XE4 上的版本是 5.2.1
  • ImageIndex := 1; 行在 vtTestGetImageIndex 函数中执行 - 设置断点时调试器停止在那里
  • 索引01 处的图像确实存在于TImageList
  • 我已经能够为不同类型的节点使用不同的图像而无需覆盖

【问题讨论】:

  • 很好的问题。使用提供的信息很容易诊断问题。

标签: delphi virtualtreeview tvirtualstringtree


【解决方案1】:

您的项目中缺少两件事。

  1. 只有索引 >= 15 的叠加层才会被绘制
  2. 你需要使用OnGetImageIndexEx,而不是普通的OnGetImageIndex

查看 VTV 的来源后,原因就很清楚了。

procedure TBaseVirtualTree.PaintImage(var PaintInfo: TVTPaintInfo; ImageInfoIndex: TVTImageInfoIndex; DoOverlay: Boolean);
....
  // Now, draw the overlay. This circumnavigates limitations in the overlay mask index (it has to be 4 bits in size,
  // anything larger will be truncated by the ILD_OVERLAYMASK).
  // However this will only be done if the overlay image index is > 15, to avoid breaking code that relies
  // on overlay image indices (e.g. when using system image lists).
  if PaintInfo.ImageInfo[iiOverlay].Index >= 15 then  //<<------!
    // Note: XPos and YPos are those of the normal images.
    DrawImage(ImageInfo[iiOverlay].Images, ImageInfo[iiOverlay].Index, Canvas, XPos, YPos,
      Style[ImageInfo[iiOverlay].Images.ImageType] or ExtraStyle, DrawEnabled);

!! Overlays with index < 15 do not get considered !!

如果您不使用OnGetImageIndexEx,从中选择叠加层的图像列表将为 nil,请参阅:

function TBaseVirtualTree.DoGetImageIndex(Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: Boolean; var Index: Integer): TCustomImageList;

// Queries the application/descendant about certain image properties for a node.
// Returns a custom image list if given by the callee, otherwise nil.

begin
  Result := nil;

  // First try the enhanced event to allow for custom image lists.
  if Assigned(FOnGetImageEx) then
    FOnGetImageEx(Self, Node, Kind, Column, Ghosted, Index, Result)
  else  !! only the ....EX works for me !!
    if Assigned(FOnGetImage) then
      FOnGetImage(Self, Node, Kind, Column, Ghosted, Index);
end;

如果我使用以下代码,您的叠加层将起作用:

procedure TForm1.vtTestGetImageIndexEx(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind;
  Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer; var ImageList: TCustomImageList);
var
  Data: PMyVtTestData;
begin

  if Node = nil then Exit;

  case Column of
    0: begin
      if Kind in [ikNormal, ikSelected] then ImageIndex:= 0
      else if Kind = ikOverlay then begin
        Data:= Sender.GetNodeData(Node);
        if Data^.isLocked then
          ImageIndex:= 1+16;
      end;
    end;
  end;
  ImageList:= Self.ImageList1;  //Or use a separate imagelist for overlays.
end;

即使不考虑叠加层的图像索引 您必须在图像列表中放置至少 15 个图像。

现在可以了:

【讨论】:

  • 优秀的答案,它就像一个魅力:) 非常感谢你
  • 感谢您提供有用的信息,但不确定为什么 15 神秘号码...
【解决方案2】:

您需要通过TImageList.Overlay指定要叠加的图像,例如:

procedure TForm1.FormCreate(Sender: TObject);
begin
  ImageList1.Overlay(1 , 0); // 1 = "Lock" index; 0=overlay index

  // second overlay - just for example:
  ImageList1.Overlay(7 , 1); // 7 = "Shortcut" index; 1=overlay index
end;

OnGetImageIndex 中,您需要使用 ImageList overlay 索引,而不是图像索引,例如:

...
if Kind = ikOverlay then begin
  if Data^.isLocked then
    ImageIndex := 0
  else
  if Data^.isShortcut then
    ImageIndex := 1
end

【讨论】:

  • 非常感谢您的回答(赞成):这是我已经尝试过的解决方案,但它不适用于我的实际用例(它仍然不起作用,我不知道为什么)我认为这是一种错误的方法。相反,它非常适合我在问题中展示的测试用例,这是一个简短而优雅的解决方案。我更愿意将@Johan 的答案保留为已接受的答案,因为在我看来,它更专注于我提供的代码。希望你不要介意
  • @fantaghirocco,我相信这是正确的方法。这也是它在所有 VT 示例中的完成方式(以及我在我们的应用程序中使用它的方式)。按照接受的答案的建议,您的“测试用例”中是否需要至少 16 张带有我的代码的图像?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多