ListView列在Delphi XE4中调整大小

时间:2013-09-19 08:46:41

标签: delphi delphi-xe4

我遇到了在Delphi XE4(在Windows 7环境中)动态调整TJVListview列宽的问题。如果列表视图中存在大量数据,则应用程序需要较长的时间进行列调整大小,有时会引发访问冲突。我们使用以下代码来调整列的大小。

for i := 0 to LV.Columns.Count -1 do
begin
  if LV.Columns.Items[i].Tag = 0 then
  begin
    LV.Columns.Items[i].Width := ColumnTextWidth;
    LV.Columns.Items[i].Width := ColumnHeaderWidth;
  end;
end;

以前使用相同的代码可以在Delphi 2009中正常工作。只有在我们使用customdrawitem事件时才会注意到这个问题(我们将图像放在listview中)。对于仅显示文本的普通列表视图,上面的代码工作正常。

我尝试使用Column AutoSize属性设置为true,但它没用。

有关如何克服此问题的任何建议。实际上,我们在应用程序中的多个位置使用了TJVlistview组件。

此致 希兰。

cODE:

1)在我的表单中,我有一个JVListview,Button和imagelist。用于加载到列表视图的按钮。 2)在Advancecustomdrawitem中,我尝试放置BMP控件并执行替代行颜色更改...

procedure TForm1.Button1Click(Sender: TObject);
var
  i, ii: Integer;
  ListItem: TListItem;
  strVal : String;
begin
  strVal := 'Test String';
  try
    ListView.Items.BeginUpdate;
    LockWindowUpdate(listview.handle);
    try
      ListView.Clear;
      for i := 1 to 15 do
      begin
        ListItem := ListView.Items.Add;
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
     end;
    finally
      // for resizing the columns based on the text size
      FitToTextWidth(ListView);
      ListView.Items.EndUpdate;
      LockWindowUpdate(0);
    end;
  except
    on E: Exception do
      MessageDlg(PWideChar(E.Message), TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0);
  end;
end;


procedure TForm1.FitToTextWidth(LV: TListView);
var
i : integer;
begin
  // Set the Column width based on based on textwidth and headerwidth
  for i := 0 to LV.Columns.Count -1 do
  begin
    if LV.Columns.Items[i].Tag = 0 then
    begin
      LV.Columns.Items[i].Width := ColumnTextWidth;
      LV.Columns.Items[i].Width := ColumnHeaderWidth;
    end;
  end;
end;

procedure TForm1.LISTVIEWAdvancedCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
  var DefaultDraw: Boolean);
       Var
R   : TRect;
C : TCanvas;
B : TBitMap;
begin
  // Set C
  C := (Sender as TListView).Canvas;
  // Set R
  R := Item.DisplayRect(drLabel);
  B := TBitMap.Create;
  B.Transparent := True;
  B.TransparentColor := clWhite;
  // based on item index set the image and change the row color
  if odd(item.Index) = true then
  begin
     ImageList.GetBitmap(0,B);
     TJvListItem( Item ).Brush.Color := clWhite;
     TJvListItem( Item ).Font.Color  := clBlack;
  end
  else
  begin
    ImageList.GetBitmap(1,B);
    TJvListItem( Item ).Brush.Color := clMoneyGreen;
    TJvListItem( Item ).Font.Color  := clBlack;
  end;
  C.Draw(R.Left + 5 ,R.Top, B);
  B.Free;
end;

以上代码适用于Delphi 2009 ...但目前正在尝试在Win 7环境中迁移到XE4 ..我的问题是,加载列表视图需要大量时间(通过调用FitToTextWidth动态执行列调整大小时)方法)..但没有这种方法它工作正常,但没有列调整大小......

1 个答案:

答案 0 :(得分:1)

当您将列的宽度设置为任何一个自动常量时,控件必须评估项目/子项目的长度,以便能够计算所需的宽度。这需要时间。

此外,当您设置列的宽度时,VCL ListView会更新所有列。

您有六列,设置其中任何一列的宽度涉及6列更新,以及FitToTextWidth过程中的虚假调用,您的代码导致读取列的所有项目/子项42次(由于VCL中的代码路径:第一列的1次,第二次的2次 - >设置6列的宽度的21次)。将您的宽度设置包含在Begin / EndUpdate调用中并删除额外的调用,您将在6轮中完成它。

procedure TForm1.FitToTextWidth(LV: TListView);
var
i : integer;
begin
  // Set the Column width based on based on textwidth and headerwidth
  LV.Columns.BeginUpdate;
  try
    for i := 0 to LV.Columns.Count -1 do
    begin
      if LV.Columns.Items[i].Tag = 0 then
      begin
//        LV.Columns.Items[i].Width := ColumnTextWidth;
        LV.Columns.Items[i].Width := ColumnHeaderWidth;
      end;
    end;
  finally
    LV.Columns.EndUpdate;
  end;
end;

由于我的测试用例没有任何AV,我无法对此发表评论。