델파이

스트링그리드(TStringGrid) 현재 행에 색깔 넣기, 교차행에 색깔 넣기, 포커스이동문제해결

미스터몽키 2017. 6. 21. 08:36

1. 스트링그리드에 현재 행에 색깔 넣기 

 

스트링그리드는 DBGrid는 RowSelect 속성이 있지만 색깔이 clHightlight 로 고정되어 있다.

또한 RowSelect 속성은 컬럼 인덱스가 0번째가 되는 특성이 있다.

 

행이 선택되어지면서 현재 선택된 컬럼인덱스를 이용해야한다면 DBGrid 에서는 dgMultiSelect 속성이 True 면 행이 하이라이트 되며 컬럼 인덱스도 현재 컬럼이 된다.

 

하지만 스트링그리드에는 MultiSelect 속성이 없으므로 다음과 같이 RowSelect 속성이 아닌 직접 행에 색깔이 넣어야한다.

 


   OnDrawCell 과 onClick 이벤트를 사용해야 한다. 

   OnClick 에서 Refresh 하지 않으면 원할하지 않다.

 

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

var

  LeftPos: Integer;

  TopPos : integer;

  CellStr: string;

begin

  with StringGrid1 do

  begin

    if ARow > 0 then  //첫행 제외

    begin

      if StringGrid1.Row = ARow then

         Canvas.Brush.Color:= clYellow  //your highlighted color

      else

          Canvas.Brush.Color:= clwhite;

    end;

 

    CellStr := TStringGrid(Sender).Cells[ACol, ARow];

 

    //세로, 가로 가운데 정렬

    TopPos  := ((Rect.Top - Rect.Bottom -TStringGrid(Sender).Canvas.TextHeight(CellStr)) div 2) + Rect.Bottom;

    LeftPos := ((Rect.Right - Rect.Left - TStringGrid(Sender).Canvas.TextWidth(CellStr)) div 2) + Rect.Left;

 

    Canvas.FillRect(Rect);

    Canvas.TextOut(LeftPos, TopPos, CellStr);

  end;

 

end;

 

procedure TForm1.StringGrid1Click(Sender: TObject);

begin

  StringGrid1.Refresh;

end;

 

(추가) 2019-08-12

delphi xe 이상에서  행 전체 컬러 넣을 때 그림 처럼 셀마다 왼쪽에 여백이 생긴다. 

 

 

 

 

해결 방법은 

 

FillRect 호출전 4 만큼 왼쪽으로 이동하면 깔끔하게 해결된다.

Rect.Left := Rect.Left-4;

 

FillRect(Rect);

 

 

 

    

(추가) 2022-02-12

경우에 따라 다음과 같이 선택된 행은 컬러 반영안되게 해도 셀 왼쪽에 일부 파란색 없이 깔끔함.

goRowSelect = True 일때도 행에 대해 작동함.

...

if (gdFocused in State) or (gdSelected in State) then        // or (gdRowSelected in State)
begin
  Canvas.Brush.Color := clHighlight;
  Canvas.Font.Color  := clHighlightText;
end;

...

 

 

2. 교차로 행에 색깔 넣기 

 

 

 

   행을 구별하기 쉽게 하기 위해 교대로 행의 색을 다르게 한다.

 

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

var

  md: integer;

  LeftPos: Integer;

  TopPos : integer;

  CellStr: string;

begin

  with StringGrid1 do

  begin

    if ARow > 0 then  //첫행 제외

    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(Rect.Left, Rect.Top, TStringGrid(Sender).Cells[ACol, ARow]);

  end;

 

 

end;

 

 

기타 참고

{

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;

end;

}

 

3. 스트링그리드 색깔 넣었을때 포커스 이동시 현재 셀 내용 지워지는 문제 해결

 

그림처럼 스트링그리드에 색깔을 변경할 경우(OnDrawCell) 포커스가 다른 컨트롤로 이동하면 현재 셀의 내용이 보이질 않는다.

 

 

 

 

(해결방법1)TStringGrid의 Defaultdrawing 속성을 False로 하고 onDrawCell에서 폰트명, 폰트크기를 직접 작성한다.

 

 

 

이때 주의할 점은 DefaultDrawing 속성이 False 라서 onDrawCell 에서 Font.Name(폰트명)  Font.Size(폰트크기) 도 직접 코딩해야한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
procedure TfrmMyMessage.sgMsgDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
  State: TGridDrawState);
begin
  // TStringGrid의 DefaultDrawing 속성을 False로 해야 포커스가
  // 다른 곳으로 옮겨져도 선택된 셀의 내용이 지워지지 않는다.
  // 단 DefaultDrawing 이 False 라서 Font.Name, Font.Size 도 직접 작성해야한다.
 
  with sgMsg do
  begin
    
    if ACol = 0 then
      Canvas.Brush.Color := $00F9F9F9      //1열 옅은 회색으로
    else
      Canvas.Brush.Color := clWindow;
 
    Canvas.Font.Name := '맑은 고딕';
    Canvas.Font.Size := 9;
 
    Canvas.FillRect(Rect);
    Canvas.TextOut(Rect.Left+2, Rect.Top+2, Cells[ACol, ARow]);    
 
  end;
 
end;
cs


 
(해결방법2) 은 TStringGrid의 Defaultdrawing 속성을 그대로 True로 하고 다음 처럼 Font.Color 를 작성한다.
이방법이 편하다.  디자인 타임에 설정한 폰트와 폰트크기가 반영되므로.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure TfrmMyMessage.sgMsgDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
  State: TGridDrawState);
begin
  with sgMsg do
  begin
    
    if ACol = 0 then
      Canvas.Brush.Color := $00F9F9F9      //1열 옅은 회색으로
    else
      Canvas.Brush.Color := clWindow;
 
    Canvas.Font.Color := clBlack;  // <= 폰트의 컬러를 입혀야 그리드에서 포커스가 Exit해도 잘 보인다.
 
    Canvas.FillRect(Rect);
    Canvas.TextOut(Rect.Left+2, Rect.Top+2, Cells[ACol, ARow]);    
 
  end;
end;
 
cs
 
또한 다음은 깔금한 선을 그릴때 유효하다.
 
1
2
3
4
5
6
7
8
9
10
//스트링그리드의 OnDrawCell에서 내용을 작성할 때 다음 코드처럼 일반적으로 작성한다.
 
    Canvas.FillRect(Rect);
    Canvas.TextOut(Rect.Left+2, Rect.Top+2, Cells[ACol, ARow]);
 
 
//그러나 셀의 내용이 셀보다 클대 셀 경계선이 깨지지 모습을 보인다. 
//이때 다음코드는 경계선이 깨지지 않고 깔금하다.
 
   Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 2, Cells[ACol, ARow]);
   Canvas.FrameRect(Rect);
cs