【问题标题】:Setting background color of selected row on TStringGrid在 TStringGrid 上设置选定行的背景颜色
【发布时间】:2011-04-07 03:45:53
【问题描述】:

我有一个 TStringGrid,其中选定的行(最多 1 个,没有多选)应该总是有不同的背景颜色(u)r。

我将 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;

【问题讨论】:

  • Mawg,这是题外话,但我怀疑 clAqua 看起来会很奇怪——它是一种非常鲜艳的颜色!请改用 clHighlight,因为它是一种系统颜色,用于表示突出显示/选定的对象。
  • 如果设置了背景色,一定要明确设置前景色。 AFAICT 您将 clAqua BG 与 clWindowText FG 结合起来,后者可以由用户通过系统的图形设置进行更改。

标签: delphi tstringgrid


【解决方案1】:

如果您尝试用不同的颜色绘制选定的行或单元格,则必须检查 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;

【讨论】:

  • 确定吗?我非常尊重你和你过去给我的帮助 - 但是 - 如果我连续点击一个单元格,那么只有那个单元格会被选中吗?不是整行?即使是(我怀疑)我的代码有什么问题?它不只是指定同一事物的两种方式吗?为什么它不起作用?
  • Uff,@Mawg 我不明白你的意思,在我提供的答案中,选定的行或单元格(取决于你是否在Options 属性中设置goRowSelect)是平局在这种情况下使用您选择的颜色clAqua 如果您想做另一件事,您必须重新表述您的问题以帮助您。
  • 如果您难以解释需要完成哪些任务,您可以在问题中附上一张示例图片,说明您想要实现的所需行为(一张图片值一千字)。
  • + 用于两者。我不知道 goRowSelect 并怀疑这就是我想要的。我会看看。谢谢。
【解决方案2】:

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

【讨论】:

  • XP,但无论如何,这肯定不能解释选择单元格的“splodgy”方式吗?如果你是对的,那么任何给定行中的每个单元格看起来都不一样吗?
【解决方案3】:

当在字符串网格中选择一个新单元格时,只有前一个单元格和新选择的单元格无效。因此,不会重绘上一行和新行的剩余单元格,从而产生您描述的效果。

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

最简洁的方法是从 TStringGrid 派生,但在大多数情况下这是不可行的。使用较新的 Delphi 版本,您可以使用类助手来实现此目的。否则你必须依赖通常的protected hack

【讨论】:

    【解决方案4】:

    这对我有用

    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;
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-10
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-06
      相关资源
      最近更新 更多