TListView自动将图像列表中的图像附加到TListView的第一列.我如何摆脱这种行为?

Luc*_*rro 1 delphi c++builder c++builder-xe8

我正在使用Embarcadero的C++ Builder XE8.我有一个ListView,并动态添加其项目列.我需要一个图像列表,因为我想将图像添加到第二列,也就是使用(ListItem-> SubItemImages [0] = i;)

似乎通过添加此图像列表,默认情况下C++ Builder认为主列还需要一个图像,因此它默认将图像列表的第0个元素附加到该列中的所有项目.我不希望这种情况发生.而是在"ID"列下,我只想要ID而不是任何图像.我怎样才能做到这一点?

屏幕截图显示了最新情况

我的代码:

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  const string firstName[] = {"Snowball", "Scavies", "Tinkerbell", "Fido", "Garfield", "Kobe"};
  const string lastName[] = {"M", "E", "O", "W", "W", "W"};
  TListColumn  *NewColumn;
  TListItem  *ListItem;
  TListView   *ListView = ListView1;

  ListView->SmallImages = ImageList1;

  ListView->ViewStyle = vsReport;
  NewColumn = ListView->Columns->Add();
  NewColumn->Caption = "ID";
  NewColumn = ListView->Columns->Add();
  NewColumn->Caption = "Node";
  NewColumn = ListView->Columns->Add();
  NewColumn->Caption = "First";
  for (int i = 0; i < sizeof( firstName ) / sizeof( firstName[0] ); i++)
  {
    char buffer[3];
    itoa(i,buffer,10);
    ListItem = ListView->Items->Add();
    ListItem->Caption = buffer;
    ListItem->SubItems->Add(firstName[i].c_str());
    ListItem->SubItems->Add(lastName[i].c_str());
    ListItem->SubItemImages[0] = i;
    //ListItem->ImageIndex = NULL;
  }
}
Run Code Online (Sandbox Code Playgroud)

Del*_*ics 6

当您将项目添加到具有ImageList关联的列表视图时,它将假定您的意图是将这些图像用于项目本身,因此添加的每个项目将被分配默认的ImageIndex0(图像列表中的第一个图像) .

从项目本身所有你需要做的去除图像替换默认的图像索引0-1,表示"无图像".

ListItem->ImageIndex = -1; 
ListItem->SubItemImages[0] = i;
Run Code Online (Sandbox Code Playgroud)

如评论中所述,这涉及不在项目标题旁边绘制图像(第0列),但列表视图仍将为这些图像留出空间,即使没有要绘制的图像:

剩下的空间用于不存在的图像

有两种方法可以避免这种情况:

  1. 不要将图像列表与列表视图关联,并使用自定义绘图来绘制任何需要图像的子项.

  2. 将列0的列宽设置为0以有效隐藏该列,并将第一个子项视为项标题.

每种方法都需要权衡利弊.

第一个要求增加自定义绘图的复杂性.第二个更直接,但意味着您需要在列表视图上启用RowSelect行为.如果没有这个,子项不能用于选择列表中的项目,也不能用任何选择突出显示.

这也意味着在任何事件处理等中你必须记住将Subitem [0]视为特殊情况(项目'标题'):

ListView->RowSelect = true;

// ..

NewColumn = ListView->Columns->Add();
NewColumn->Caption = "Not Used";
NewColumn->Width   = 0;
NewColumn = ListView->Columns->Add();
NewColumn->Caption = "ID";

// ..

// No need to set ListItem->Caption since it is hidden

ListItem->SubItems->Add(buffer);  // subitem[0] = 'the item'
ListItem->SubItems->Add(firstName[i].c_str());
ListItem->SubItems->Add(lastName[i].c_str());
ListItem->SubItemImages[1] = i;
Run Code Online (Sandbox Code Playgroud)

一些好奇的用户可能会调整 列[0]并发现您隐藏的秘密.:)

  • 您不需要所有者绘制来解决此问题.在`vsReport`模式下,第0列用于在分配图像列表时显示`TListItem.ImageIndex`(即使它是-1).所以只需添加但隐藏第0列(将其`Width`设置为0),然后为ID添加一个单独的列(您必须使用`ListItem-> SubItems [0]`而不是`ListItem-> Caption`来持有ID值). (3认同)
  • @Remy一个简洁的想法,只要你很乐意使用**RowSelect = true**,因为第一个子项目的行为与*Column [0]`的行为不完全相同.特别是,如果没有**RowSelect**,子项目是不可选择的,如果你需要将subitem [0]视为特殊情况子项(而不仅仅是项目处理与子项处理),它可能会使事件处理复杂化.但是**RowSelect**通常是可接受的,在某种程度上应该是默认值,但它不是,也可能不总是*是可取的.:) (3认同)