TDBGrid:OnDrawColumnCell 数据重叠

TDBGrid: OnDrawColumnCell Data is overlapping

我正在开发 Delphi 10.2SQL Server 2008.

我必须修改 TDBGrid 中的一些值。当我使用 OnDrawColumnCell 修改值时,当我单击该列时,数据被重叠,并且在 Delphi 7.[=21= 中工作正常]

示例代码:

创建 table 并在 SQL Server 2008.

中插入一些数据
CREATE TABLE [dbo].[Persons](
    [P_ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [LastName] [varchar](15) NOT NULL,
)
insert into Persons (LastName) values ('LastName')

创建新的 VCL 表单应用程序 - Delphi

要在 DBGrid 上显示数据,我正在使用 TADOCOnnectionTADOQueryTDataSourceTDBGrid

TADOQuery.SQL设置为"select LastName from Persons"

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, DBGrids, DB, ADODB, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    ADOConnection1: TADOConnection;
    ADOQuery1: TADOQuery;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    procedure FormShow(Sender: TObject);
    procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
      DataCol: Integer; Column: TColumn; State: TGridDrawState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
begin
  ADOQuery1.Active := False;
  ADOQuery1.Active := True;
end;

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
Var
  CellData : String;
begin
  CellData := Column.Field.DisplayText;

  if Column.Field.FieldName = 'LastName' then
  begin
    CellData := 'change';
    DBGrid1.Canvas.TextRect(Rect, Rect.Left, Rect.Top, CellData);
  end
  else
    DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, state);
end;

end.

这是一个一般绘图问题,与 SQL 服务器或特定的 TDBGrid 无关。这同样适用于绘制到 VCL TCanvas 或类似的东西。

在绘制文本之前清除区域

您正在呼叫 Canvas.TextRect(..),但仅此而已。文本将被绘制,但仅此而已。您必须先清理该区域:想象在绘制黑色文本之前先绘制白色背景。

TDBGrid提供了一个方便的方法DrawCellBackground(..)。由于此方法不是 public,因此需要利用助手 类.

来实现它

实现示例

以下代码使用 DrawCellHighlight(..) 在单元格被选中时清除单元格绘制区域,否则使用 DrawCellBackground(..)

type
    TDBGridHelper = class helper for TDBGrid
        public const textPaddingPx = 2; // Siehe TDBGrid::DefaultDrawColumnCell
        public procedure writeText(
            const   inRect:         TRect;
            const   text:           String;
            const   State:          TGridDrawState;
            const   columnIndex:    Integer
        );
    end;

procedure TDBGridHelper.writeText(
    const   inRect:         TRect;
    const   text:           String;
    const   State:          TGridDrawState;
    const   columnIndex:    Integer
);
const
    cellGridPx = 1;
var
    backgroungRect: TRect;
begin
    backgroungRect := inRect;
    backgroungRect.Inflate(-cellGridPx, -cellGridPx);

    if (Vcl.Grids.gdSelected in State) then
        DrawCellHighlight(inRect, State, columnIndex, 0)
    else
        DrawCellBackground(backgroungRect, self.Color, State, Columnindex, 0);

    Canvas.TextRect(
        inRect,
        inRect.Left + textPaddingPx,
        inRect.Top + textPaddingPx,
        text
    );
end;

利用 TDBGrid.OnDrawColumnCell 事件是绝对正确的,您现在可以将其简化为

procedure TYourFrame.dbGridDrawColumnCell(
    Sender: TObject;
    const Rect: TRect;
    DataCol: Integer;
    Column: TColumn;
    State: TGridDrawState
);
var
    columnText:     String;
begin
    columnText := '---';
    if Assigned(Column.Field) then begin
        if (Column.FieldName = 'yourField') then
            columnText := getDeviationColumnText(Column.Field.AsSingle)
        else
            // This is the default text
            columnText := Column.Field.DisplayText; 
    end;
    (Sender as TDBGrid).writeText(Rect, columnText, State, Column.Index);
end;

如果浏览 30 个表格太单调乏味,您可以关闭 "Runtime themes" 以恢复 Windows 2000 年的花哨外观和随之而来的绘图算法。

  1. 选择“项目”>“选项”>“应用程序”。
  2. 清除“启用运行时主题”复选框。

来源:http://docwiki.embarcadero.com/RADStudio/en/Disabling_Themes_in_the_IDE_and_in_Your_Application