设置 TStringGrid 上选定行的背景颜色

发布于 2024-10-31 01:44:25 字数 1097 浏览 1 评论 0原文

我有一个 TStringGrid,其中所选行(最多 1,无多选)应始终具有不同的背景颜色。

我将 DefaultDrawing 属性设置为 false,并为 OnDrawCell 事件提供一个方法,如下所示 - 但它不起作用。我什至无法准确描述它是如何不起作用的;我想如果我能的话我就已经解决了这个问题。可以说,它不是具有相同背景颜色的完整行,而是一个大杂烩。多行具有一些“选定”颜色的单元格,并且并非选定行的所有单元格都具有选定的颜色。

请注意,我将单元格的行与 strnggrid 的行进行了比较;我无法检查所选单元格状态,因为仅选择了所选行的单元格。

procedure TForm1.DatabaseNamesStringGridDrawCell(Sender: TObject;
                                                 ACol, ARow: Integer;
                                                 Rect: TRect;
                                                 State: TGridDrawState);

  var cellText :String;
begin
   if gdFixed in State then
      DatabaseNamesStringGrid.Canvas.Brush.Color := clBtnFace
   else
   if ARow = DatabaseNamesStringGrid.Row then
      DatabaseNamesStringGrid.Canvas.Brush.Color := clAqua
   else
      DatabaseNamesStringGrid.Canvas.Brush.Color := clWhite;

   DatabaseNamesStringGrid.Canvas.FillRect(Rect);
   cellText := DatabaseNamesStringGrid.Cells[ACol, ARow];
   DatabaseNamesStringGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, cellText);
end;

I have a TStringGrid where the selected row (max 1, no multi-select) should always have a different background colo(u)r.

I set the DefaultDrawing property to false, and provide a method for the OnDrawCell event, shown below - but it is not working. I can't even describe exactly how it is not working; I supect that if I could I would already have solved the problem. Suffice it to say that instead of having complete rows all with the same background colour it is a mish-mash. Muliple rows have some cells of the "Selected" colour and not all cells of the cselected row have the selected colour.

Note that I compare the cell's row with the strnggrid's row; I can't check the cell state for selected since only cell of the selected row is selected.

procedure TForm1.DatabaseNamesStringGridDrawCell(Sender: TObject;
                                                 ACol, ARow: Integer;
                                                 Rect: TRect;
                                                 State: TGridDrawState);

  var cellText :String;
begin
   if gdFixed in State then
      DatabaseNamesStringGrid.Canvas.Brush.Color := clBtnFace
   else
   if ARow = DatabaseNamesStringGrid.Row then
      DatabaseNamesStringGrid.Canvas.Brush.Color := clAqua
   else
      DatabaseNamesStringGrid.Canvas.Brush.Color := clWhite;

   DatabaseNamesStringGrid.Canvas.FillRect(Rect);
   cellText := DatabaseNamesStringGrid.Cells[ACol, ARow];
   DatabaseNamesStringGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, cellText);
end;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

怎言笑 2024-11-07 01:44:25

如果您尝试用不同的颜色绘制选定的行或单元格,则必须检查 state 变量中的 gdSelected 值。

procedure TForm1.DatabaseNamesStringGridDrawCell(Sender: TObject;
                                                 ACol, ARow: Integer;
                                                 Rect: TRect;
                                                 State: TGridDrawState);
var
  AGrid : TStringGrid;
begin
   AGrid:=TStringGrid(Sender);

   if gdFixed in State then //if is fixed use the clBtnFace color
      AGrid.Canvas.Brush.Color := clBtnFace
   else
   if gdSelected in State then //if is selected use the clAqua color
      AGrid.Canvas.Brush.Color := clAqua
   else
      AGrid.Canvas.Brush.Color := clWindow;

   AGrid.Canvas.FillRect(Rect);
   AGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, AGrid.Cells[ACol, ARow]);
end;

if you are trying of paint the selected row or cell with a different color you must check for the gdSelected value in the state var.

procedure TForm1.DatabaseNamesStringGridDrawCell(Sender: TObject;
                                                 ACol, ARow: Integer;
                                                 Rect: TRect;
                                                 State: TGridDrawState);
var
  AGrid : TStringGrid;
begin
   AGrid:=TStringGrid(Sender);

   if gdFixed in State then //if is fixed use the clBtnFace color
      AGrid.Canvas.Brush.Color := clBtnFace
   else
   if gdSelected in State then //if is selected use the clAqua color
      AGrid.Canvas.Brush.Color := clAqua
   else
      AGrid.Canvas.Brush.Color := clWindow;

   AGrid.Canvas.FillRect(Rect);
   AGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, AGrid.Cells[ACol, ARow]);
end;
枕头说它不想醒 2024-11-07 01:44:25

您启用了运行时主题吗?运行时主题会覆盖您尝试为 Windows Vista 及更高版本强制实施的任何配色方案。

Do you have run-time themes enabled? Run-time themes override any colour scheme you try to enforce for Windows Vista and up.

浅笑轻吟梦一曲 2024-11-07 01:44:25

这对我有用

procedure TFmain.yourStringGrid(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
  State: TGridDrawState);
var
  md: integer;
begin
  with yourStringGrid do 
    begin
           if yourStringGrid,Row = ARow then
              Canvas.Brush.Color:= clYellow  //your highlighted color
           else begin
                 md := Arow mod 2;
                 if md <> 0 then Canvas.Brush.Color:= $00BADCC1 else //your alternate color
                 Canvas.Brush.Color:= clwhite;
           end;
           Canvas.FillRect(Rect);
           Canvas.TextOut(L, Rect.top + 4, cells[ACol, ARow]);
        end;
end;

刷新网格

procedure TFmain.yourStringGridClick(Sender: TObject);
begin
  yourStringGrid.Refresh;
end;

注意:有一点延迟,但在其他方面效果很好。
(用于德尔福XE2)

This works for me

procedure TFmain.yourStringGrid(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
  State: TGridDrawState);
var
  md: integer;
begin
  with yourStringGrid do 
    begin
           if yourStringGrid,Row = ARow then
              Canvas.Brush.Color:= clYellow  //your highlighted color
           else begin
                 md := Arow mod 2;
                 if md <> 0 then Canvas.Brush.Color:= $00BADCC1 else //your alternate color
                 Canvas.Brush.Color:= clwhite;
           end;
           Canvas.FillRect(Rect);
           Canvas.TextOut(L, Rect.top + 4, cells[ACol, ARow]);
        end;
end;

Refresh the grid

procedure TFmain.yourStringGridClick(Sender: TObject);
begin
  yourStringGrid.Refresh;
end;

Note: Has a little latency, but otherwise works great.
(Used in Delphi XE2)

放血 2024-11-07 01:44:25

当在字符串网格中选择新单元格时,只有前一个和新选择的单元格才会失效。因此,前一行和新行的剩余单元格不会重新绘制,从而达到您所描述的效果。

一种解决方法是为受影响的行调用 InvalidateRow,但这是受保护的方法,您必须找到一种方法从 OnSelectCell 事件处理程序访问此方法。根据您的 Delphi 版本,有不同的方法可以实现这一点。

最干净的方法是从 TStringGrid 派生,但在大多数情况下这是不可行的。在较新的 Delphi 版本中,您可以使用类助手来实现此目的。否则,您必须依赖通常的受保护的黑客

When a new cell is selected in a stringgrid only the previous and the new selected cell are invalidated. Thus the remaining cells of the previous and new row are not redrawn, giving the effect you describe.

One workaround would be to call InvalidateRow for both affected rows, but this is a protected method and you have to find a way to reach this method from an OnSelectCell event handler. Depending on your Delphi version there are different ways to accomplish that.

The cleanest way would be to derive from TStringGrid, but in most cases this is not feasible. With a newer Delphi version you can use a class helper to achieve this. Otherwise you have to rely on the usual protected hack.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文