delphidelphi-2010custom-drawstringgrid

Add graphical bar to a StringGrid col


Using Delphi 2010 and a TStringGrid component, I currently display five filds from a database query.

Here is a simplied example of what i am doing

//set up the grid

procedure TGriddata.FormCreate(Sender: TObject);
begin
 grdMain.Rows[0].commatext:='"One","Two","Three","Four","Five"';
 grdMain.ColWidths[0]:= 50;
 grdMain.ColWidths[1]:= 175;
 grdMain.ColWidths[2]:= 175;
 grdMain.ColWidths[3]:= 100;
 grdMain.ColWidths[4]:= 300;
end;

//display the data in the grid //note, I am not showing my creation, execution, or destroy of the query

procedure TGriddata.load;
begin
 ... 
 grdMain.Cells[0,row]:= FieldByName('one').AsString;
 grdMain.Cells[1,row]:= FieldByName('two').AsString;
 grdMain.Cells[2,row]:= FieldByName('three').AsString;
 grdMain.Cells[3,row]:= FieldByName('four').AsString;
 //draw progress bar here
 ...
end;

One of the columns ("Five") needs to display a navy blue horizontal bar in the col. It should also diplay some text centered in the bar. I have no expereince using the custom drawing. What properties do i set to only custom draw the one column and use the default drawing for the other columns?


Solution

  • Add the text to the cells like you normally would. But you have to draw those bars in the OnDrawCell event. Leave DefaultDrawing as is (True by default), and erase the already drawn cell text in those columns by filling it in advance:

    procedure TForm1.grdMainDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    var
      Progress: Single;
      R: TRect;
      Txt: String;
    begin
      with TStringGrid(Sender) do
        if (ACol = 4) and (ARow >= FixedRows) then
        begin
          Progress := StrToFloatDef(Cells[ACol, ARow], 0) / 100;
          Canvas.FillRect(Rect);
          R := Rect;
          R.Right := R.Left + Trunc((R.Right - R.Left) * Progress);
          Canvas.Brush.Color := clNavy;
          Canvas.Rectangle(R);
          Txt := Cells[ACol, ARow] + '%';
          Canvas.Brush.Style := bsClear;
          IntersectClipRect(Canvas.Handle, R.Left, R.Top, R.Right, R.Bottom);
          Canvas.Font.Color := clHighlightText;
          DrawText(Canvas.Handle, PChar(Txt), -1, Rect, DT_SINGLELINE or
            DT_CENTER or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX);
          SelectClipRgn(Canvas.Handle, 0);
          ExcludeClipRect(Canvas.Handle, R.Left, R.Top, R.Right, R.Bottom);
          Canvas.Font.Color := clWindowText;
          DrawText(Canvas.Handle, PChar(Txt), -1, Rect, DT_SINGLELINE or
            DT_CENTER or DT_VCENTER or DT_END_ELLIPSIS or DT_NOPREFIX);
          SelectClipRgn(Canvas.Handle, 0);
        end;
    end;
    

    Custom drawn bars in StringGrid

    For more options, you might consider this DrawStatus routine.