2011-04-07 78 views
1

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

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

Mawg,这是脱离主题,但我怀疑clAqua看起来很奇怪 - 它是一种非常明亮的颜色!尝试使用clHighlight,因为它是代表高亮/选定对象的系统颜色。 – 2011-04-07 05:40:57

+0

如果设置背景色,请务必明确设置前景色。 AFAICT将clAqua BG与clWindowText FG结合在一起,后者可由用户通过系统的图形设置进行更改。 – 2011-04-07 07:00:30

回答

4

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

你确定吗?我非常尊重你和你过去给予我的帮助 - *但是* - 当然,如果我点击一行中的一个单元格,那么只有那个单元格被选中?不是整行?即使它(我怀疑)是什么与我的代码worng?这不仅仅是指定同一件事的两种方式吗?为什么它不起作用? – Mawg 2011-04-07 05:54:19

+1

Uff,@Mawg我不明白你是什么意思,在我提供的答案中,所选择的行或单元格(取决于你是否在'Options'属性中设置'goRowSelect')是用你选择的颜色绘制的如果你想做另一件事情,你必须改述你的问题来帮助你,这个案例'clAqua'。 – RRUZ 2011-04-07 06:03:07

+1

如果你很难解释哪些需要完成,你可以在你的问题中附上一个你希望实现的期望行为的示例图像(一张图片胜过千言万语)。两者均为 – RRUZ 2011-04-07 06:07:17

2

您是否启用了运行时主题?运行时主题会覆盖您尝试为Windows Vista及更高版本实施的所有配色方案。

+0

XP,但无论如何,当然这并不能解释细胞被选中的“splodgy”方式吗?如果你是对的,那么在任何给定行中的每个单元格是不是看起来一样? – Mawg 2011-04-07 05:55:30

2

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

一种解决方法是为受影响的行调用InvalidateRow,但这是一种受保护的方法,您必须找到一种方法才能从OnSelectCell事件处理程序中访问此方法。取决于你的Delphi版本,有不同的方法来完成这个。

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

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)