3

How can I hide the grid lines separating empty cells from the adjacent cells in a TListView control? It would be like the HTML colspan table attribute, or Excel's "merge cells" command. I would like for cells with text in them to retain their normal borders.

Example

Rob Kennedy
  • 156,531
  • 20
  • 258
  • 446
Kermia
  • 3,963
  • 11
  • 56
  • 104
  • What do you mean by removing empty columns? – Sertac Akyuz Feb 28 '11 at 18:07
  • After investigating this for a while, it doesn't seem like there is any robust solution. – Andreas Rejbrand Feb 28 '11 at 18:25
  • I have never quite understood why people upvotes question that are not yet unambiguous. – Andreas Rejbrand Feb 28 '11 at 19:23
  • 2
    Me too, @Andreas. But for that matter, I sometimes wonder why people *answer* such questions. – Rob Kennedy Feb 28 '11 at 19:26
  • Kermia, I have rewritten your question so that it matches what everyone seems to have interpreted it to mean. If you really wanted to ask something different, then please post another question that more clearly explains what you want. Keep in mind that you can't *remove* a column for just some rows. Since you're already drawing pictures, maybe you could draw a picture of what you want the control to look like. – Rob Kennedy Feb 28 '11 at 19:28
  • @Rob @Andreas I personally wonder why people guess at what the poster actually wants the question to be and edit the question to be something utterly different. Surely it's better to let the person asking the question tell you what they want answered? – David Heffernan Feb 28 '11 at 19:47
  • @Rob : Thank you so much Mr Kennedy :) – Kermia Feb 28 '11 at 20:13

2 Answers2

3

You could use TVirtualStringTree. It has option toAutoSpanColumns which will automatically span empty columns.

Linas
  • 5,265
  • 1
  • 22
  • 33
  • +1. Since my attempts suggest that the Windows tree view cannot do this (robustly), a third-party component might be a good choice. – Andreas Rejbrand Feb 28 '11 at 20:43
  • 1
    @Andreas - Not sure, but perhaps because the answer does not start with *Not answering the question, but..* .. – Sertac Akyuz Feb 28 '11 at 22:54
  • @Sertac: Yes, now that you say so, it feels rather obvious. Still, it is always a good practice to combine a downvote with a helpful comment. – Andreas Rejbrand Feb 28 '11 at 22:58
1

There seems not to exist any robust solution to this problem.

A bad solution, however, is

procedure TForm4.FormShow(Sender: TObject);
var
  i: integer;
begin
  ListView1.ViewStyle := vsReport;
  ListView1.Columns.Add.Caption := 'Col 1';
  ListView1.Columns.Add.Caption := 'Col 2';
  ListView1.Columns.Add.Caption := 'Col 3';
  ListView1.GridLines := false; // You cannot have grid lines...
  for i := 0 to 10 do
    with ListView1.Items.Add do
    begin
      if i <> 5 then
      begin
        Caption := 'Test';
        SubItems.Add('test');
        SubItems.Add('test');
      end
      else
        Caption := 'This is a very, very long caption';
    end;
end;

var
  ColWidths: array of integer;

procedure TForm4.ListView1AdvancedCustomDraw(Sender: TCustomListView;
  const ARect: TRect; Stage: TCustomDrawStage; var DefaultDraw: Boolean);
var
  i, j: Integer;
begin
  if Stage <> cdPrePaint then Exit;
  if length(ColWidths) <> TListView(Sender).Columns.Count then
  begin
    SetLength(ColWidths, TListView(Sender).Columns.Count);
    Exit;
  end;
  for i := 0 to length(ColWidths) - 1 do
    if ColWidths[i] <> Sender.Column[i].Width then
    begin
      Sender.Invalidate;
      for j := 0 to length(ColWidths) - 1 do
        ColWidths[i] := Sender.Column[i].Width;
    end;
end;

procedure TForm4.ListView1AdvancedCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
  var DefaultDraw: Boolean);
var
  r: TRect;
begin
  DefaultDraw := (Item.SubItems.Count <> 0);
  if not DefaultDraw then
  begin
    FillRect(Sender.Canvas.Handle, Item.DisplayRect(drBounds), GetStockObject(WHITE_BRUSH));
    r := Item.DisplayRect(drBounds);
    DrawText(Sender.Canvas.Handle, Item.Caption, length(Item.Caption), r, DT_SINGLELINE or DT_LEFT or DT_VCENTER)
  end;
end;

Listview colspan is hard to get right. Don't do it.

This is bad because it is not robust. It flickers, it's buggy, and it is "hacky". It might not work well in future versions of Windows. Basically, the Windows list view control isn't supposed to do HTML-like colspan, I think.

Andreas Rejbrand
  • 95,177
  • 8
  • 253
  • 351