delphi – TStringGrid合并单元格绘图

这个链接/ pic显示了我想用TStringGrid实现的目标.

链接/图片显示了我的下面代码产生的结果.

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.

这是我的unit1.dfm文件内容.

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

问题似乎是在StringGridDrawCell中的合并代码正好在//尝试将3个单元格合并到一个注释中.

我敢肯定它可能是显而易见的,但对于我的生活,我看不到它.

注意:如果有人可以将链接转换为嵌入式图像,那将非常受欢迎,因为我似乎没有足够的声誉来发布图像.

解决方法

试试这个:
unit Unit1;

interface

uses
  Windows,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] := 'Count';
  StringGrid.Cells[3,1] := 'Weight %';
  StringGrid.Cells[4,1] := 'Count';
  StringGrid.Cells[6,1] := 'Weight %';
  StringGrid.Cells[7,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,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,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);

    case ACol of
      1..9: begin
        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.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,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,DT_WORDBREAK or DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS)
    else
      DrawText(StringGrid.Canvas.Handle,DT_SINGLELINE or DT_CENTER or DT_BOTTOM or DT_END_ELLIPSIS);
  end
  else begin
    CellText := StringGrid.Cells[ACol,-2);
    case ACol of
      0..1,7: begin
        DrawText(StringGrid.Canvas.Handle,DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS);
      end;
      2..3,5..6,8..9: begin
        DrawText(StringGrid.Canvas.Handle,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

相关文章

ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c++ 调用, 抽空研究了一下该库的最新版 ,把...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和EDX)2个变址和指针寄存器(ESI和EDI) 2个指针寄...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的功能是:将源操作数送到目的操作数中,即:...
有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。 1.CreateProcess因为使用复杂...
API原型: Declare Function MoveFileEx& Lib "kernel32" Alias "MoveFileExA" (By...