3

我有一个 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;
4

4 回答 4

6

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

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;
于 2011-04-07T05:06:53.677 回答
2

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

于 2011-04-07T04:02:43.257 回答
2

在 stringgrid 中选择新单元格时,仅前一个单元格和新选择的单元格无效。因此,前一行和新行的剩余单元格不会重绘,从而产生您描述的效果。

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

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

于 2011-04-07T08:45:55.237 回答
2

这对我有用

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 中使用)

于 2014-10-10T16:27:14.630 回答