关于 Delphi 10 TDrawGrid:Delphi 10 TDrawGrid – 如何正确刷新行? | 珊瑚贝

Delphi 10 TDrawGrid – How do I get rows to refresh properly?


使用 Delphi 10.2 Tokyo。

我使用 DrawCell 方法使一行中的所有列与所选单元格的颜色相同。这允许我让用户单击不同的单元格,但仍显示”选定”行。

这使用 OnSelectCell 方法使原始行和新选择的行无效。多年来一直使用这种方法。

如果我有一个带有水平滚动条的网格,则当向右滚动并且用户单击单元格时,该网格不会正确绘制。

下面是一个使用 TDrawGrid 和 OnDrawCell 事件和 OnSelectCell 事件的简单示例:

表格 (DFM) 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = ‘Form1’
  ClientHeight = 299
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = 11
  Font.Name = ‘Tahoma’
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object DrawGrid1: TDrawGrid
    Left = 0
    Top = 0
    Width = 635
    Height = 299
    Align = alClient
    Color = clWhite
    ColCount = 15
    DefaultColWidth = 65
    DefaultRowHeight = 48
    DefaultDrawing = False
    DrawingStyle = gdsGradient
    RowCount = 12
    GradientEndColor = clBtnFace
    GradientStartColor = clBtnFace
    Options = [goThumbTracking]
    ParentShowHint = False
    ShowHint = True
    TabOrder = 0
    OnDrawCell = DrawGrid1DrawCell
    OnSelectCell = DrawGrid1SelectCell
    ColWidths = (
      65
      65
      65
      65
      65
      65
      65
      65
      65
      65
      65
      65
      65
      65
      65)
    RowHeights = (
      48
      48
      48
      48
      48
      48
      48
      48
      48
      48
      48
      48)
  end
end

单位 (PAS) 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,     System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Math;

type
  TGridCracker = class(TDrawGrid)// required to access protected method Invalidaterow – info gleaned from Team B member Peter Below on the Internet
  private
  public
  end;

  TForm1 = class(TForm)
    DrawGrid1: TDrawGrid;
    procedure DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
    procedure DrawGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var MyCanvas : TCanvas;
  str : string;
  MyRect : TRect;
begin
  MyCanvas := TDrawGrid(Sender).Canvas;

  MyCanvas.Font.Name := ‘Arial’; // drawgrid uses Tahoma 8pt as its default font, not Arial
  MyCanvas.Font.Size := 9;
  MyCanvas.Brush.Color := TDrawGrid(Sender).FixedColor;
  MyCanvas.Font.Color := TDrawGrid(Sender).Font.Color;
  MyCanvas.FillRect(Rect);

  if (ARow = 0) then begin
    str := EmptyStr;
    if (ACol > 0) then begin
        str := ACol.ToString;
    end
    else begin
      str := ‘TEST’;
    end;

    MyCanvas.Font.Color := clblack; // clGray;
    MyRect.Left := Rect.Left + 1;
    MyRect.Top := Rect.Top + 3;
    MyRect.Right := Rect.Right 1;
    MyRect.Bottom := Rect.Bottom 3;
    MyCanvas.FillRect(MyRect);
    MyCanvas.Brush.Color := clGray;
    MyCanvas.FrameRect(MyRect);
    MyCanvas.Brush.Color := clWhite;
    MyCanvas.Font.Style := MyCanvas.Font.Style + [fsBold];

    MyRect.Top := MyRect.Top + 2;
    DrawText(MyCanvas.Handle, pChar(str), 1, MyRect, DT_VCENTER or DT_CENTER);

    MyCanvas.Font.Style := MyCanvas.Font.Style [fsBold];
  end
  else begin
    if (ACol = 0) then begin
      MyCanvas.Brush.Color := clMaroon;
      MyCanvas.FillRect(Rect);
    end
    else begin//ACol > 0
      if ARow = DrawGrid1.Row then begin
        MyCanvas.Brush.Color := clBlue;
      end
      else begin
        MyCanvas.Brush.Color := clwhite;
      end;

      MyCanvas.FillRect(Rect);

      // other cell drawing of text happens after here
    end;
  end;
end;

procedure TForm1.DrawGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean);
begin
  TGridCracker(Sender).InvalidateRow(TGridCracker(Sender).Row);
  TGridCracker(Sender).InvalidateRow(ARow);
end;

end.

运行程序。

单击水平滚动条,使第 14 列可见。

单击第 2 行中的第 13 列。

单击第 3 行中的第 12 列。

注意到真正混乱的选择模式了吗?

这是结果的屏幕截图:

screen

理想情况下,应该有一排蓝色单元格,而不是乱七八糟的。第 3 行应该是纯蓝色。

在 OnSelectCell 方法中调用 DrawGrid1.Refresh 甚至无法修复它。

关于如何使它真正起作用的任何想法?我不能对这个网格使用 RowSelect。

干杯!

TJ

  • 请参阅 qc.embarcadero.com/wc/qcmain.aspx?d=81060 这是一个自 delphi 开始以来就存在的错误


除了不必要的闪烁之外,您的代码似乎没有任何错误。这可以通过使用 OnDrawCell 事件的 State 来解决。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
procedure TForm1.DrawGrid1DrawCell(Sender: TObject; ….
var MyCanvas : TCanvas;
  str : string;
  MyRect : TRect;
begin
  MyCanvas := TDrawGrid(Sender).Canvas;

  if gdFixed in State then begin
    MyCanvas.Font.Name := ‘Arial’; // drawgrid uses Tahoma 8pt as its default font, not Arial
    MyCanvas.Font.Size := 9;
    MyCanvas.Brush.Color := TDrawGrid(Sender).FixedColor;
    MyCanvas.Font.Color := TDrawGrid(Sender).Font.Color;
    MyCanvas.FillRect(Rect);
  end;

  if (ARow = 0) then begin
   

错误在 TCustomGrid 的 InvalidateRow 中,它不考虑可能的滚动。列方式相同。

您可以使用受保护的 BoxRect 方法,该方法使用 GridRectToScreenRect(私有)方法将单元格位置转换为屏幕坐标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
procedure TForm1.DrawGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean);
var
  Grid: TDrawGrid;
  GR, R: TRect;
begin
  Grid := Sender as TDrawGrid;
  if ARow = Grid.Row then
    Exit;

  GR.Left := Grid.LeftCol;
  GR.Top := Grid.Row;
  GR.Width := Grid.VisibleColCount;
  GR.Height := 0;

  R := TGridCracker(Grid).BoxRect(GR.Left, GR.Top, GR.Right, GR.Bottom);
  InvalidateRect(Grid.Handle, R, False);

  GR.Top := ARow;
  GR.Bottom := ARow;

  R := TGridCracker(Grid).BoxRect(GR.Left, GR.Top, GR.Right, GR.Bottom);
  InvalidateRect(Grid.Handle, R, False);
end;



这是由于 VCL TCustomGrid.InvalidateRow(和 TCustomGrid.InvalidateCol)例程中的一个错误:

1
2
3
4
5
6
7
8
9
10
11
procedure TCustomGrid.InvalidateRow(ARow: Longint);
var
  Rect: TGridRect;
begin
  if not HandleAllocated then Exit;
  Rect.Top := ARow;
  Rect.Left := 0; // this should be Rect.Left:=LeftCol; –> index of the first column in the scrollable region that is visible
  Rect.Bottom := ARow;
  Rect.Right := VisibleColCount+1;
  InvalidateRect(Rect);
end;

解决此问题的方法:

1
2
3
4
5
6
7
8
9
10
11
12
   type TGridCracker = class(TDrawGrid)
   protected
    procedure InvalidateRow(ARow: Longint);
   end;

   procedure TGridCracker.InvalidateRow(ARow: Integer);
   var i: Integer;
   begin
     if not HandleAllocated then
        Exit;
     for i := 0 to ColCount1 do // this will invalidate all cells, visible and hidden
         InvalidateCell(i, ARow);

1
2
3
     for i := LeftCol to LeftCol+VisibleColCount do // this will invalidate only visible cells
         InvalidateCell(i, ARow);    
   end;

来源:https://www.codenong.com/51368662/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_9389.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?