【问题标题】:Using Canvas.TextOut in DBGrid - Delphi XE 3在 DBGrid 中使用 Canvas.TextOut - Delphi XE 3
【发布时间】:2017-10-24 04:10:13
【问题描述】:

请,我需要帮助使用 Canvas: 当用户将鼠标移动到 DBGrid 的标题列上时, 标题描述在 Delphi XE 3 中消失了。 DelphI 7 中不会出现此问题。

按照下面的代码:

unit Unit1;

interface

uses

Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Graphics, Controls, Forms, Dialogs, Data.DB, Datasnap.DBClient,
Grids, DBGrids, Types, StdCtrls;

type
TAccessDBGrid = class(TCustomGrid);

type
TForm1 = class(TForm)

DataSource1: TDataSource;
grid1: TDBGrid;
cdsTabela: TClientDataSet;
cdsTabelacodigo_1: TIntegerField;
cdsTabelacodigo_2: TIntegerField;`enter code here`

procedure grid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);

procedure FormCreate(Sender: TObject);

procedure FormResize(Sender: TObject);

procedure grid1TitleClick(Column: TColumn);

private
    { Private declarations }
public
    { Public declarations }
end;

var
Form1: TForm1;

implementation
    {$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
    begin
        cdsTabela.CreateDataSet;
    end;

procedure TForm1.FormResize(Sender: TObject);
    begin
        grid1.Refresh;
    end;

procedure TForm1.grid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
S1 : string;

begin

with TAccessDBGrid(grid1) do
begin
    RowHeights[0] := 29;
    Canvas.Brush.Color := clBtnFace;
    case Column.Index of
    0:
    begin
        Column.Title.Caption := '';
        S1 := 'Code';
    end;
    1:
    begin
        Column.Title.Caption := '';
        S1 := 'Description';
    end;
end;

TDBGrid(Sender).Canvas.Font.Color:= clBlack;
Canvas.TextOut(Rect.Left + 3, 19, S1);
end;
end;

procedure TForm1.grid1TitleClick(Column: TColumn);
begin
ShowMessage('Title Click! ');
end;

end

有关更多信息,请参阅我发布的答案。

【问题讨论】:

  • 在您已经开始绘制行之后,您希望如何更改行高?我在这台机器上没有可用的 D7,但我认为它在那里也不起作用。而是在 FormCreate 事件中设置行的高度。为什么在对Canvas.TextOut 的调用中硬编码19 而不是使用Rect.Top 的偏移量?当你改为这样做而不是使用19 时会发生什么?而且您的代码毫无意义;您正在删除每一行的 Title.Caption,并在每一行的每个单元格中从 S1 中绘制相同的文本。这段代码从来没有工作过。
  • @KenWhite:你说“这段代码从来没有工作过”是完全正确的。它在我的 D7 中肯定不能正常工作。

标签: delphi vcl delphi-xe3


【解决方案1】:

您发布的答案中包含的额外信息使您更容易理解您要做什么,这很好。请在以后的问题中尝试这样做,因为您更有可能更快地得到更好的答案。

无论如何,我建议您用 Mike Shkolnik 的 TSMDBGrid 替换您的 TDBGrid。请参阅:http://www.scalabium.com/smdbgrid.htm 并观看动画。

他的网格包含一个OnDrawColumnTitle 事件,我认为它比尝试使用 TDBGrid 更容易实现您想要的。我从你们的 cmets 那里得知,你们已经遵循了这个建议,并且成功地完成了你们想做的事情。

原答案如下:

我同意 Ken White 所说的,但除此之外,我认为您的代码 被误解了。要明白我的意思,试试这个:

  1. 保存代码编辑器不重叠的 IDE 调试布局 你的 Form1。这样做的目的是为了不强制 Form1 重新绘制 IDE 在断点上停止。

  2. 将 DefaultDrawing 设置为 False。关键在于将其设置为 True 隐藏了你的 Grid1DrawColumnCell 是多么糟糕。

  3. 在Grid1DrawColumnCell 的第一行放置一个断点,即 with TAccessDBGrid(grid1).

  4. 编译并运行。请注意,调试器在断点处停止了几个 表格在屏幕上绘制时的时间,但在那之后它不会 完全停止你的血压。因此,一旦表单出现在屏幕上,您的自定义绘画就永远不会发生,直到您导致网格刷新,例如使用表单的 OnResize 处理程序。

  5. 那么是什么原因导致您移动鼠标后标题标题栏为空白 在网格之上。答案是,你愿意!看看为什么...

  6. 在VCL.DBGrids.Pas中,在TCustomDBGrid.DrawCell中找到DrawTitleCell,并放上BP WriteText(Canvas, TextRect, LFrameOffs, LFrameOffs, Caption, Alignment,...

  7. 再次运行应用程序到您的Grid1DrawColumnCell 已执行的位置 并且调试器在步骤 6 中设置的WriteText BP 上停止。评估Caption 你会看到它是空的(因为你的Grid1DrawColumnCell 已经清除了它,当然)。我想您可以在 DrawColumnCell 退出之前将您的 S1 值分配给列标题的 Caption ,但是绘制它 确实仍然是一团糟,你会看到如果你尝试例如

    case Column.Index of
    0: begin
    //   Column.Title.Caption := '';
         S1 := 'Code';
         Column.Title.Caption := S1;
    end;
    1: begin
    //   Column.Title.Caption := '';
         S1 := 'Description';
         Column.Title.Caption := S1;
    end;
    

QED

所以基本上你是在浪费你的时间在你的Grid1DrawColumnCell 上。如果你 想知道是否可以自定义绘制列标题/标题,如果可以,如何, 我建议你在做一些研究后问一个新的q。如果你没有找到任何东西,你可以考虑派生一个 TCustomDBGrid 后代并覆盖它的DrawCell;这样您就可以更好地控制整个绘图过程,并且可能更接近您想要实现的目标。

顺便说一句,以上是基于在 Delphi Seatlle 中编译的应用程序,它比 XE3 更新,但我怀疑这有什么不同。

【讨论】:

  • 我添加了一个答案来解释我的问题。
  • 谢谢 Martyn,您使用 TSMDBGrid 而不是 TDBGrid 的建议解决了我的问题,而且它做得更多!我为 2 列创建了一个乐队,现在可以工作了!恭喜!
【解决方案2】:

我使用 Canvas.TextOut 而不是 Title.Caption 的原因是 我需要在 Title 中写 2 行:

        Tests
Test One    Test Two

我使用“19”而不是 Rect.Top,因为我想在 Title 中书写。 如果我使用 Rect.Top,文本将绘制在列的编辑区域

Canvas.TextOut(Rect.Left + 3, 19, S1);

下面是我的真实代码:

在 Grid1DrawColumnCell 中:

with TAccessDBGrid(grid1) do
begin
  RowHeights[0] := 37;
  Canvas.Brush.Color := clBtnFace;

  case Column.Index of
  0: begin
       Column.Title.Caption := '';
       S1 := 'Code';
     end;
  1: begin
       Column.Title.Caption := '';
       Canvas.Font.Color := clBlack;

       S1 := 'Tests';

       Canvas.Brush.Style := bsSolid;
       Canvas.Brush.Color := clBtnFace;
       Canvas.FillRect(Types.Rect(Rect.Left, 0, Rect.Left + 120, 18));
       Canvas.TextOut(Rect.Left + 3, 1, S1);
       Canvas.Brush.Style := bsSolid;

       S1 := 'Test One';
     end;
  2: begin
       Column.Title.Caption := '';
       S1 := 'Test Two';
     end;
 end;

  Canvas.Font.Color:= clBlack;
  Canvas.TextOut(Rect.Left + 3, 19, S1);
end;

【讨论】:

  • 好吧,如果您一开始就发布了您的真实代码,那将会有所帮助!
  • 对不起,我想我会简化代码以便您理解。但我做不到。拜托,你能帮我吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
  • 2011-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多