Q&A

  • 팁란에 타락천사님이 올리신 스트링 그리드에 체크 박스 넣기 문제점....
밑에 답변주신 이중철님 정말 감사합니다. 왼쪽위에 잔상 check박스가 남던 문제는 해결 되었습니다..

다시 스트링 그리드에 대한 질문인데요.

팁란에 있는 스트링 그리드에 체크 박스 넣기 방법과

홍성락님께서 올리신 방법을 조합해서 사용하려고 합니다.

그런데 문제가 발생합니다. 스크롤이 없을 땐 문제가 없는데 row값이 커지면서 스크롤을 하게 되면

찍힌 체크의 잔상이 남아 체크가 엉망이 되버립니다.

최소화 시켰다가 다시 확대하면 제대로 찍혀 있는걸로 봐서

체크된게 옮겨지는게 아니라 스크롤 되고 다시 그리면서 잔상이 남는거 같습니다.

팁란에 타락천사님이 올리신 코드를 보니 제가 사용한 방법이 그 방법인거 같은데

밑에 체크박스 잔상을 어떻게 해야하는가에 대한 질문이 몇개 있는데

그에 대한 해결 방안이 안올라와 있네요. 머슴님이 수정하신 방법으로도 해결이 안되구요.

질문만 있고 답변이 없으니 답답합니다. 아시는 분(이미 이 방법을 사용하고 계시는 것같은 홍성락님이나 타락천사님도... 부탁드립니다... T_T)은 꼭 답변해 주세요.

밑에는 제 소스입니다.

-------------------------------------------------------------------

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, Grids, jpeg, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    StringGrid1: TStringGrid;
    procedure FormShow(Sender: TObject);
    procedure CheckBoxMouseUp(Sender: TObject; Button: TMouseButton;
        Shift: TShiftState; X, Y: integer);
    procedure StringGridInCheckBoxCreate(sg :TStringGrid; Col, Row :Integer; pChecked :Boolean);
    procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.FormShow(Sender: TObject);
var
  i, j : integer;
begin
With StringGrid1 Do Begin
  RowCount := 20;
  ColCount := 4;
  ColWidths[1] := 60;
  ColWidths[3] := 230;
  for i := 0 to ColCount-2 do begin
    for j := 0 to RowCount-1 do begin
      if i = 1 then
        StringGridInCheckBoxCreate(StringGrid1,i,j,True)
      ELSE
        StringGridInCheckBoxCreate(StringGrid1,i,j,false);
    end;
  end;
end;
end;

procedure TForm1.StringGridInCheckBoxCreate(sg :TStringGrid; Col, Row :Integer; pChecked :Boolean);

var
  LeftWidth, iCnt :Integer;
begin
  if not (sg.Objects[Col, Row] is TCheckBox) then
    sg.Objects[Col, Row] := TCheckBox.Create(sg);
  with TCheckBox(sg.Objects[Col, Row]) do
  begin
    OnMouseUp  := CheckBoxMouseUp;
    Parent     := sg;
    Checked    := pChecked;
    BoundsRect := sg.CellRect(Col, Row);
    Width      := 14;
    Height     := sg.RowHeights[Row];
    Hint       := inttostr(Row);
    showHint   := False;
    visible    := false;
  end;
end;

procedure TForm1.CheckBoxMouseUp(Sender: TObject; Button: TMouseButton;
        Shift: TShiftState; X, Y: integer);
var
  i, Row: integer;
begin
with TCheckBox(Sender) do
  Row := StrToInt(Hint);
  for i := 0 to StringGrid1.ColCount-1 do begin
    if (StringGrid1.objects[i,Row] is TCheckBox) then
      TCheckBox(StringGrid1.objects[i,Row]).Checked := false;
  end;
  TCheckBox(Sender).Checked := true;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
     CellStr  : String;
begin
    if (TStringGrid(Sender).Objects[ACol, ARow] is TCheckBox) then begin
       with TCheckBox(TStringGrid(Sender).Objects[ACol, ARow]) do begin
            top  := Rect.Top;
            Left := (Rect.Left+Rect.Right) Div 2 - 7;
            visible := true;
       end;
       with TStringGrid(Sender) do begin
//            Canvas.Font := Font;
//            Canvas.TextRect(Rect, Rect.left+14,(Rect.Top+Rect.Bottom-Font.Size-2) div 2, TStringGrid(Sender).Cells[ACol,ARow] );
       end;
    end
    else
    if ACol = 4 then // 가운데 정렬
    begin
      with TStringGrid(Sender).Canvas do
      begin
        CellStr := TStringGrid(Sender).Cells[ACol, ARow];
        Left := ((Rect.Right - Rect.Left - TStringGrid(Sender).Canvas.TextWidth(CellStr)) div 2) + Rect.Left;
        FillRect(Rect);
        TextOut(Left, Rect.Top + 2, CellStr);
      end;
    end;
    END;
end.
4  COMMENTS
  • Profile
    이중철 2003.05.01 00:19
    일단 Visible 로 제어했던 부문 빼시고
    체크박스 만드는 StringGridInCheckBoxCreate 에 이 루틴을
    추가해 보세요..
        top        := sg.CellRect(Col, Row).Top;
        Left       := sg.CellRect(Col, Row).Left + sg.ColWidths[Col]  Div 2 - 7;
    TopLeftChanged 이 부문 추가해서 넣으시고
    procedure TForm1.StringGrid1TopLeftChanged(Sender: TObject);
    var i , j : integer;
    begin
        StringGrid1.Visible := false;
        for i := 0 to StringGrid1.RowCount - 1 do
          for j := 0 to 2 do begin
            StringGrid1DrawCell(StringGrid1, j, i, StringGrid1.CellRect(j,i), [gdSelected        ]        );
          end;
        StringGrid1.Visible := True;

    end;

    에고 아까 올린것은 테스트를 안해봐서요.. 쩝 지송..
    이놈의 스트링그리드 짜증나는 컨트롤이네요..

  • Profile
    고가람 2003.05.01 00:46
    감사합니다.. T_T

    이제 잔상 남는건 해결이 됐습니다.

    그런데 이렇게 바꾸니 없어졌던 왼쪽 제일 위의 체크박스가

    다시 등장하네요 -_-;;;;

    게다가 다시 그리느리 번쩍번쩍하기까지...

    델파이를 시작한지 얼마 안되는지라 스트링 그리드는 처음 써봤는데..

    사용하기가 불편하네요. 아무래도 이놈은 포기하고 다른 놈으로 옮겨가야 할듯합니다.. T_T

    참 그리고 TMS 그리드가 AdvstringGrid를 말씀하시는건가요?

    이건 상용이던데.. T_T

    어쨌든 다시 한번 감사드립니다.


    -------------------------------------------------------------------

    procedure TForm1.FormShow(Sender: TObject);
    var
      i, j : integer;
    begin
    With StringGrid1 Do Begin
      RowCount := 20;
      ColCount := 4;
      ColWidths[1] := 60;
      ColWidths[3] := 230;
      for i := 0 to ColCount-2 do begin
        for j := 0 to RowCount-1 do begin
          if i = 1 then
            StringGridInCheckBoxCreate(StringGrid1,i,j,True)
          ELSE
            StringGridInCheckBoxCreate(StringGrid1,i,j,false);
        end;
      end;
    end;
    end;

    procedure TForm1.StringGridInCheckBoxCreate(sg :TStringGrid; Col, Row :Integer; pChecked :Boolean);

    var
      LeftWidth, iCnt :Integer;
    begin
      if not (sg.Objects[Col, Row] is TCheckBox) then
        sg.Objects[Col, Row] := TCheckBox.Create(sg);
      with TCheckBox(sg.Objects[Col, Row]) do
      begin
        OnMouseUp  := CheckBoxMouseUp;
        Parent     := sg;
        Checked    := pChecked;
        BoundsRect := sg.CellRect(Col, Row);
        Width      := 14;
        Height     := sg.RowHeights[Row];
        top        := sg.CellRect(Col, Row).Top;
        Left       := sg.CellRect(Col, Row).Left + sg.ColWidths[Col]  Div 2 - 7;
        Hint       := inttostr(Row);
        showHint   := False;
      end;
    end;

    procedure TForm1.CheckBoxMouseUp(Sender: TObject; Button: TMouseButton;
            Shift: TShiftState; X, Y: integer);
    var
      i, Row: integer;
    begin
    with TCheckBox(Sender) do
      Row := StrToInt(Hint);
      for i := 0 to StringGrid1.ColCount-1 do begin
        if (StringGrid1.objects[i,Row] is TCheckBox) then
          TCheckBox(StringGrid1.objects[i,Row]).Checked := false;
      end;
      TCheckBox(Sender).Checked := true;
    end;

    procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    var
         CellStr  : String;
    begin
        if (TStringGrid(Sender).Objects[ACol, ARow] is TCheckBox) then begin
           with TCheckBox(TStringGrid(Sender).Objects[ACol, ARow]) do begin
                top  := Rect.Top;
                Left := (Rect.Left+Rect.Right) Div 2 - 7;
           end;
        end
        else
        if ACol = 4 then // 가운데 정렬
        begin
          with TStringGrid(Sender).Canvas do
          begin
            CellStr := TStringGrid(Sender).Cells[ACol, ARow];
            Left := ((Rect.Right - Rect.Left - TStringGrid(Sender).Canvas.TextWidth(CellStr)) div 2) + Rect.Left;
            FillRect(Rect);
            TextOut(Left, Rect.Top + 2, CellStr);
          end;
        end;
    END;

    procedure TForm1.StringGrid1TopLeftChanged(Sender: TObject);
    var i , j : integer;
    begin
        StringGrid1.Visible := false;
        for i := 0 to StringGrid1.RowCount - 1 do
          for j := 0 to 2 do begin
            StringGrid1DrawCell(StringGrid1, j, i, StringGrid1.CellRect(j,i), [gdSelected        ]        );
          end;
        StringGrid1.Visible := True;
    end;
  • Profile
    이중철 2003.05.01 01:02
    eDonkey 있어요  에공 불법을 조장하네 쩝..

    그리고 왼쪽 제일 위의 체크박스는

    생성시에 조절하면 되요 위에 올려놓은것에 포함되어 있어요.

    이렇게 해도 문제는 다 해결이 안되더군요

    한번 유심히 보면 중간에 체크박스 하나를 체크하고

    위로 스크롤 하다보면 체크한 Row가 맨 위로 갈 즈음에

    하나만 체크되어 있어야 하는데 2개가 체크되어 있더군요

    쩝 이건 어떻게 해결해야 할지 아직 모르겠어요..

    그럼 이만 즐코

  • Profile
    타락천사 2003.04.30 22:43
    안녕하세여.. 타락임다..

    그냥 상용컴포넌트 쓰시는게 좋겠습니다..^^;;

    체크박스를 이미지로 올리고 TStringGrid.OnDrawCell event 에서 적절하게 그려주면 될것 같은데................

    찾아 보면 그런 컴포넌트가 있을 겁니다.

    필요한 기능을 가진 컴포넌트가 있으면, 그것을 쓰는 것이 좋습니다.

    즐푸하세여..

    타락천사..

    사족: 컴포넌트를 못찾으면, 쪽지주세요. 제가 찾아 드리거나 컴포넌트 만들어 드리져.