2014-11-05 19 views
5

Dieser Link/Bild zeigt, was ich versuche, mit einem TStringGrid zu erreichen.TStringGrid merge cell drawing

enter image description here

Dieser Link/pic zeigen, was unter meinen Code in sich führt.

enter image description here

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, Grids; 

type 
    TForm1 = class(TForm) 
    StringGrid: TStringGrid; 
    procedure FormCreate(Sender: TObject); 
    procedure StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); 
    private 
    public 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
const 
    cProdWidth = 70; 
    cCountWidth = 45; 
    cWeightWidth = 55; 
var 
    Index: Integer; 
    Col, Row: Integer; 
begin 
    StringGrid.ColCount := 10; 
    StringGrid.RowCount := 2; 
    StringGrid.Cells[1, 0] := 'Shoulder'; 
    StringGrid.ColWidths[1] := cProdWidth; 
    StringGrid.Cells[4, 0] := 'Barrel'; 
    StringGrid.ColWidths[4] := cProdWidth; 
    StringGrid.Cells[7, 0] := 'Leg'; 
    StringGrid.ColWidths[7] := cProdWidth; 

    StringGrid.Cells[0, 1] := 'Carcass Prod'; 
    StringGrid.ColWidths[0] := cProdWidth; 
    StringGrid.Cells[1, 1] := 'Product'; 
    StringGrid.Cells[2, 1] := 'Count'; 
    StringGrid.ColWidths[2] := cCountWidth; 
    StringGrid.Cells[3, 1] := 'Weight %'; 
    StringGrid.ColWidths[3] := cWeightWidth; 
    StringGrid.Cells[4, 1] := 'Product'; 
    StringGrid.Cells[5, 1] := 'Count'; 
    StringGrid.ColWidths[5] := cCountWidth; 
    StringGrid.Cells[6, 1] := 'Weight %'; 
    StringGrid.ColWidths[6] := cWeightWidth; 
    StringGrid.Cells[7, 1] := 'Product'; 
    StringGrid.Cells[8, 1] := 'Count'; 
    StringGrid.ColWidths[8] := cCountWidth; 
    StringGrid.Cells[9, 1] := 'Weight %'; 
    StringGrid.ColWidths[9] := cWeightWidth; 
    StringGrid.Invalidate; 
end; 

procedure TForm1.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); 
var 
    CellText: String; 
begin 
    if (ACol > 0) 
    then begin 
      CellText := StringGrid.Cells[ACol, ARow]; 
      if ((ARow = 0) and (ACol in [1, 4, 7])) 
      then begin 
        // Attempt to merge 3 cells into one 
        Rect.Right := StringGrid.ColWidths[ACol] + StringGrid.ColWidths[ACol + 1] + StringGrid.ColWidths[ACol + 2]; 
        StringGrid.Canvas.Brush.Color := clWindow; 
        StringGrid.Canvas.Brush.Style := bsSolid; 
        StringGrid.Canvas.Pen.Style := psClear; 
        StringGrid.Canvas.FillRect(rect); 
        DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS); 
       end; 
      if (ACol in [1,2,3,7,8,9]) 
      then begin 
        StringGrid.Canvas.Brush.Color := clWebLinen; 
        StringGrid.Canvas.FillRect(Rect); 
       end 
      else StringGrid.Canvas.Brush.Color := clWindow; 
      if (ARow > 0) 
      then StringGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top, CellText); 
     end; 
end; 

end. 

Und das ist meine unit1.dfm Dateiinhalte.

object Form1: TForm1 
    Left = 0 
    Top = 0 
    Caption = 'Form1' 
    ClientHeight = 371 
    ClientWidth = 606 
    Color = clBtnFace  
    Font.Charset = DEFAULT_CHARSET 
    Font.Color = clWindowText 
    Font.Height = -11 
    Font.Name = 'Tahoma' 
    Font.Style = [] 
    OldCreateOrder = False 
    OnCreate = FormCreate 
    PixelsPerInch = 96 
    TextHeight = 13 
    object StringGrid: TStringGrid 
    Left = 0 
    Top = 0 
    Width = 606 
    Height = 371 
    Align = alClient 
    ColCount = 1 
    FixedCols = 0 
    RowCount = 1 
    FixedRows = 0 
    TabOrder = 0 
    OnDrawCell = StringGridDrawCell 
    ExplicitLeft = 160 
    ExplicitTop = 88 
    ExplicitWidth = 320 
    ExplicitHeight = 120 
    end 
end 

Das Problem scheint mit der Verschmelzung Code in StringGridDrawCell knapp unter dem //Attempt to merge 3 cells into one Kommentar zu sein.

Ich bin sicher, es ist wahrscheinlich etwas offensichtlich, aber für das Leben von mir kann ich es nicht sehen.

HINWEIS: Wenn jemand die Links in eingebettete Bilder verwandeln könnte, würde das sehr geschätzt werden, da ich nicht genug Ansehen habe, um Bilder zu posten.

Antwort

3

Versuchen Sie folgendes:

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, 
    Controls, Forms, Dialogs, Grids; 

type 
    TForm1 = class(TForm) 
    StringGrid: TStringGrid; 
    procedure StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; 
     Rect: TRect; State: TGridDrawState); 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
const 
    cProdWidth = 70; 
    cCountWidth = 45; 
    cWeightWidth = 55; 
    cNoSelection: TGridRect = (Left: -1; Top: -1; Right: -1; Bottom: -1); 
begin 
    StringGrid.ColCount := 10; 
    StringGrid.RowCount := 3; 
    StringGrid.FixedRows := 2; 

    StringGrid.RowHeights[0] := StringGrid.Canvas.TextHeight('Shoulder') + 4; 
    StringGrid.RowHeights[1] := (StringGrid.Canvas.TextHeight('Carcass Product') + 4) * 2; 

    StringGrid.ColWidths[0] := cProdWidth; 
    StringGrid.ColWidths[1] := cProdWidth; 
    StringGrid.ColWidths[2] := cCountWidth; 
    StringGrid.ColWidths[3] := cWeightWidth; 
    StringGrid.ColWidths[4] := cProdWidth; 
    StringGrid.ColWidths[5] := cCountWidth; 
    StringGrid.ColWidths[6] := cWeightWidth; 
    StringGrid.ColWidths[7] := cProdWidth; 
    StringGrid.ColWidths[8] := cCountWidth; 
    StringGrid.ColWidths[9] := cWeightWidth; 

    StringGrid.Cells[1, 0] := 'Shoulder'; 
    StringGrid.Cells[4, 0] := 'Barrel'; 
    StringGrid.Cells[7, 0] := 'Leg'; 

    StringGrid.Cells[0, 1] := 'Carcass'#10'Product'; 
    StringGrid.Cells[1, 1] := 'Product'; 
    StringGrid.Cells[2, 1] := 'Count'; 
    StringGrid.Cells[3, 1] := 'Weight %'; 
    StringGrid.Cells[4, 1] := 'Product'; 
    StringGrid.Cells[5, 1] := 'Count'; 
    StringGrid.Cells[6, 1] := 'Weight %'; 
    StringGrid.Cells[7, 1] := 'Product'; 
    StringGrid.Cells[8, 1] := 'Count'; 
    StringGrid.Cells[9, 1] := 'Weight %'; 

    StringGrid.Cells[0, 2] := '22-110'; 
    StringGrid.Cells[1, 2] := '22-120'; 
    StringGrid.Cells[2, 2] := '2'; 
    StringGrid.Cells[3, 2] := '35'; 
    StringGrid.Cells[4, 2] := '22-130'; 
    StringGrid.Cells[5, 2] := '1'; 
    StringGrid.Cells[6, 2] := '25'; 
    StringGrid.Cells[7, 2] := '22-140'; 
    StringGrid.Cells[8, 2] := '2'; 
    StringGrid.Cells[9, 2] := '40'; 

    StringGrid.Selection := cNoSelection; 
    StringGrid.Invalidate; 
end; 

procedure TForm1.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; 
    Rect: TRect; State: TGridDrawState); 
var 
    CellText: String; 
begin 
    Rect := StringGrid.CellRect(ACol, ARow); 

    if ARow = 0 then 
    begin 
    case ACol of 
     1, 4, 7: begin 
     Rect.Right := Rect.Right + StringGrid.GridLineWidth; 
     end; 
     2, 5, 8: begin 
     Rect.Left := Rect.Left - StringGrid.GridLineWidth; 
     Rect.Right := Rect.Right + StringGrid.GridLineWidth; 
     end; 
     3, 6, 9: begin 
     Rect.Left := Rect.Left - StringGrid.GridLineWidth; 
     end; 
    end; 
    case ACol of 
     0, 4..6: begin 
     StringGrid.Canvas.Brush.Color := clWindow; 
     end; 
     1..3, 7..9: begin 
     StringGrid.Canvas.Brush.Color := clWebLinen; 
     end; 
    end; 
    end else 
    begin 
    if (State * [gdSelected, gdRowSelected]) <> [] then 
     StringGrid.Canvas.Brush.Color := clHighlight 
    else 
     StringGrid.Canvas.Brush.Color := clWindow; 
    end; 

    StringGrid.Canvas.Brush.Style := bsSolid; 
    StringGrid.Canvas.Pen.Style := psClear; 
    StringGrid.Canvas.FillRect(Rect); 

    StringGrid.Canvas.Brush.Style := bsClear; 
    StringGrid.Canvas.Pen.Style := psSolid; 
    StringGrid.Canvas.Pen.Color := clWindowText; 

    if ARow = 0 then 
    begin 
    StringGrid.Canvas.MoveTo(Rect.Left, Rect.Top); 
    StringGrid.Canvas.LineTo(Rect.Right, Rect.Top); 

    case ACol of 
     0, 1, 4, 7: begin 
     StringGrid.Canvas.MoveTo(Rect.Left, Rect.Top); 
     StringGrid.Canvas.LineTo(Rect.Left, Rect.Bottom); 
     end; 
    end; 

    if ACol = 9 then 
    begin 
     StringGrid.Canvas.MoveTo(Rect.Right-1, Rect.Top); 
     StringGrid.Canvas.LineTo(Rect.Right-1, Rect.Bottom); 
    end; 

    StringGrid.Canvas.MoveTo(Rect.Left, Rect.Bottom); 
    StringGrid.Canvas.LineTo(Rect.Right, Rect.Bottom); 
    end 
    else if ARow = 1 then 
    begin 
    StringGrid.Canvas.MoveTo(Rect.Left, Rect.Top); 
    StringGrid.Canvas.LineTo(Rect.Right, Rect.Top); 

    case ACol of 
     1..9: begin 
     StringGrid.Canvas.MoveTo(Rect.Left, Rect.Top); 
     StringGrid.Canvas.LineTo(Rect.Left, Rect.Bottom); 
     end; 
    end; 

    if ACol = 9 then 
    begin 
     StringGrid.Canvas.MoveTo(Rect.Right-1, Rect.Top); 
     StringGrid.Canvas.LineTo(Rect.Right-1, Rect.Bottom); 
    end; 

    StringGrid.Canvas.MoveTo(Rect.Left, Rect.Bottom-1); 
    StringGrid.Canvas.LineTo(Rect.Right, Rect.Bottom-1); 
    end 
    else begin 
    case ACol of 
     1..9: begin 
     StringGrid.Canvas.MoveTo(Rect.Left, Rect.Top); 
     StringGrid.Canvas.LineTo(Rect.Left, Rect.Bottom); 
     end; 
    end; 

    if ACol = 9 then 
    begin 
     StringGrid.Canvas.MoveTo(Rect.Right-1, Rect.Top); 
     StringGrid.Canvas.LineTo(Rect.Right-1, Rect.Bottom); 
    end; 
    end; 

    if (State * [gdSelected, gdRowSelected]) <> [] then 
    begin 
    StringGrid.Canvas.Brush.Color := clHighlight; 
    StringGrid.Canvas.Font.Color := clHighlightText; 
    end else 
    begin 
    StringGrid.Canvas.Brush.Color := clWindow; 
    StringGrid.Canvas.Font.Color := clWindowText; 
    end; 
    StringGrid.Canvas.Brush.Style := bsClear; 

    if ARow = 0 then 
    begin 
    case ACol of 
     1..3: begin 
     Rect.TopLeft := StringGrid.CellRect(1, 0).TopLeft; 
     Rect.BottomRight := StringGrid.CellRect(3, 0).BottomRight; 
     CellText := StringGrid.Cells[1, 0]; 
     end; 
     4..6: begin 
     Rect.TopLeft := StringGrid.CellRect(4, 0).TopLeft; 
     Rect.BottomRight := StringGrid.CellRect(6, 0).BottomRight; 
     CellText := StringGrid.Cells[4, 0]; 
     end; 
     7..9: begin 
     Rect.TopLeft := StringGrid.CellRect(7, 0).TopLeft; 
     Rect.BottomRight := StringGrid.CellRect(9, 0).BottomRight; 
     CellText := StringGrid.Cells[7, 0]; 
     end; 
    end; 

    Rect.Inflate(-2, -2); 
    DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER or DT_END_ELLIPSIS); 
    end 
    else if ARow = 1 then 
    begin 
    CellText := StringGrid.Cells[ACol, ARow]; 
    Rect.Inflate(-2, -2); 
    if ACol = 0 then 
     DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_WORDBREAK or DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS) 
    else 
     DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_SINGLELINE or DT_CENTER or DT_BOTTOM or DT_END_ELLIPSIS); 
    end 
    else begin 
    CellText := StringGrid.Cells[ACol, ARow]; 
    Rect.Inflate(-2, -2); 
    case ACol of 
     0..1, 4, 7: begin 
     DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS); 
     end; 
     2..3, 5..6, 8..9: begin 
     DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_SINGLELINE or DT_RIGHT or DT_VCENTER or DT_END_ELLIPSIS); 
     end; 
    end; 
    end; 
end; 

end. 

object Form1: TForm1 
    Left = 0 
    Top = 0 
    Caption = 'Form1' 
    ClientHeight = 371 
    ClientWidth = 606 
    Color = clBtnFace 
    Font.Charset = DEFAULT_CHARSET 
    Font.Color = clWindowText 
    Font.Height = -11 
    Font.Name = 'Tahoma' 
    Font.Style = [] 
    OldCreateOrder = False 
    OnCreate = FormCreate 
    PixelsPerInch = 96 
    TextHeight = 13 
    object StringGrid: TStringGrid 
    Left = 0 
    Top = 0 
    Width = 606 
    Height = 371 
    Align = alClient 
    ColCount = 1 
    FixedCols = 0 
    RowCount = 1 
    FixedRows = 0 
    Options = [goRangeSelect, goRowSelect] 
    TabOrder = 0 
    OnDrawCell = StringGridDrawCell 
    end 
end 

grid

2

Es gibt andere String Komponenten der Lage, Zellen zu verschmelzen. Zum Beispiel this one die ich selbst geschrieben (Download-Quellen: NLDStringGrid + NLDSparseList) mit möglicherweise dieses Ergebnis:

NLDStringGrid

var 
    R: TRect; 
begin 
    NLDStringGrid1.Columns.Add; 
    NLDStringGrid1.Columns.Add; 
    NLDStringGrid1.Cells[1, 1] := 'Sample test'#13#10'Second line'; 
    NLDStringGrid1.Columns[1].MultiLine := True; 
    NLDStringGrid1.AutoRowHeights := True; 
    SetRect(R, 2, 2, 3, 3); 
    NLDStringGrid1.MergeCells(TGridRect(R), True, True); 
    NLDStringGrid1.ColWidths[2] := 40; 
    NLDStringGrid1.Cells[2, 2] := 'Sample test'#13#10'Second line'; 
end; 
1

Das Hauptproblem ist, dass das folgende Stück Code, der die Zelle Hintergrund mit einem Unentschieden clWebLinen Farbe wird immer nach dem Code ausgeführt, der die Zelle zusammenführt.

if (ACol in [1,2,3,7,8,9]) 
    then begin 
     StringGrid.Canvas.Brush.Color := clWebLinen; 
     StringGrid.Canvas.FillRect(Rect); 
     end; 

diesen Code nicht auf Zellen laufen verschmolzen werden, zusammen mit dem Merge Code für jede Zelle in der Zusammenführung ausgeführt wird (z. B. 1,2,3. Nicht nur 1) behebt die meist Probleme.

Das letzte Stück zentriert den Text über die verbundenen Zellen, was durch Ändern von DT_LEFT zu DT_CENTER erreicht werden kann.

DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER or DT_END_ELLIPSIS); 

Unten ist die vollständige Lösung.

procedure TForm1.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); 
const 
    cGridLineWidth = 1; 
    cGroupCount = 3; 
var 
    CellText: String;  
    ProdCol: Integer; 
    CountCol: Integer; 
    WeightCol: Integer; 
    Found: Boolean; 
begin 
    if ((ARow = 0) and (ACol > 0)) 
    then begin 
      ProdCol := 1; 
      CountCol := 2; 
      WeightCol := 3; 
      Found := False; 
      while (not Found) do 
      begin 
       if ((ACol = ProdCol) or (ACol = CountCol) or (ACol = WeightCol)) 
       then begin 
         Found := True; 
         if (ACol = ProdCol) 
         then begin 
           Rect.Right := Rect.Right + StringGrid.ColWidths[CountCol] + cGridLineWidth + StringGrid.ColWidths[WeightCol] + cGridLineWidth; 
          end 
         else if (ACol = CountCol) 
         then begin 
           Rect.Right := Rect.Right + StringGrid.ColWidths[WeightCol] + cGridLineWidth; 
           Rect.Left := Rect.Left - cGridLineWidth - StringGrid.ColWidths[ProdCol]; 
          end 
         else begin 
           Rect.Left := Rect.Left - cGridLineWidth - StringGrid.ColWidths[CountCol] - cGridLineWidth - StringGrid.ColWidths[ProdCol]; 
          end; 
         CellText := StringGrid.Cells[ProdCol, ARow]; 
         if (ACol in [1,2,3,7,8,9]) 
         then StringGrid.Canvas.Brush.Color := clWebLinen 
         else StringGrid.Canvas.Brush.Color := clWindow; 
         StringGrid.Canvas.Brush.Style := bsSolid; 
         StringGrid.Canvas.Pen.Style := psClear; 
         StringGrid.Canvas.FillRect(rect); 
         StringGrid.Canvas.Pen.Style := psSolid; 
         DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER or DT_END_ELLIPSIS); 
        end; 
       ProdCol := ProdCol + cGroupCount; 
       CountCol := CountCol + cGroupCount; 
       WeightCol := WeightCol + cGroupCount; 
      end; 
     end 
    else begin 
      CellText := StringGrid.Cells[ACol, ARow]; 
      if (ACol in [1,2,3,7,8,9]) 
      then StringGrid.Canvas.Brush.Color := clWebLinen 
      else StringGrid.Canvas.Brush.Color := clWindow; 
      if (ARow = 0) 
      then Exit; 
      StringGrid.Canvas.FillRect(Rect); 
      DrawText(StringGrid.Canvas.Handle, PChar(CellText), Length(CellText), Rect, DT_SINGLELINE or DT_LEFT or DT_VCENTER); 
     end; 
end;