2014-06-21 1 views
-1

발견 된 델파이 코드 here을 수정하여 세 열 stringgrid에 체크 박스 상태를 저장했습니다. 문제는 셀을 두 번 클릭하여 전환해야한다는 것입니다. goEditing을 설정하면 클릭 한 번으로 상태를 설정할 수 있지만 클릭 한 번만 클릭하면 체크 박스가 보이지 않게됩니다. 이러한 편집 상태 문제를 방지하려면 어떻게합니까?StringGrid의 체크 상자가 정상적으로 전환되지 않습니다. Delphi

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, Grids; 

type 
    TForm1 = class(TForm) 
    gridOwnerDraw: TStringGrid;//must set goEditing True 
    procedure gridOwnerDrawDrawCell(Sender: TObject; ACol, ARow: Integer; 
     Rect: TRect; State: TGridDrawState); 
    procedure gridOwnerDrawClick(Sender: TObject); 
    procedure FormResize(Sender: TObject); 
    private 
    { Private declarations } 
    FInMouseClick: boolean; 
    function GetBtnRect(ACol, ARow: integer; complete: boolean): TRect; 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

const 
    TXT_MARG: TPoint = (x: 4; y: 2); 
    BTN_WIDTH = 12; 
var 
    Checked1: array[1..4] of boolean = (false, true, false, true); 
    Checked2: array[1..4] of boolean = (true, false, true, false); 

//Returns rectangle where button will be drawn: 
procedure TForm1.FormResize(Sender: TObject); 
begin 
    gridOwnerDraw.Invalidate; 
end; 

function TForm1.GetBtnRect(ACol, ARow: integer; complete: boolean): TRect; 

    function MakeBtnRect(Alignment: TAlignment; cellrect: TRect; complete: boolean): TRect; 
    var 
    rowHeight: integer; 
    begin 
    result := cellrect; 
    rowheight := cellrect.bottom - cellrect.top; 

    case Alignment of 
     taLeftJustify: 
     begin 
      result.Right := cellrect.left + BTN_WIDTH + TXT_MARG.x + (TXT_MARG.x div 2); 
      if not complete then 
      begin 
      result.Top := cellrect.Top + ((RowHeight - BTN_WIDTH) div 2); 
      result.Left := cellrect.Left + ((RowHeight - BTN_WIDTH) div 2); 
      result.Bottom := result.Top + BTN_WIDTH; 
      result.Right := result.Left + BTN_WIDTH; 
      end; 
     end; 
     taRightJustify: 
     begin 
      result.Left := cellrect.Right - BTN_WIDTH - TXT_MARG.x - TXT_MARG.x; 
      if result.left < cellrect.left then 
      result.left := Cellrect.left; 

      if not complete then 
      begin 
      result.top := cellrect.top + ((RowHeight - BTN_WIDTH) div 2); 
      result.left := result.left + TXT_MARG.x; 
      result.right := Result.left + BTN_WIDTH; 
      result.Bottom := result.top + BTN_WIDTH; 
      end; 
     end; 
     taCenter: 
     begin 
      result.left := result.left + ((cellrect.Right - cellrect.left) div 2) - (BTN_WIDTH div 2) - TXT_MARG.x; 
      if result.left < cellrect.Left then 
      result.left := cellrect.left; 
      result.right := result.left + BTN_WIDTH + TXT_MARG.x + TXT_MARG.x; 
      if not complete then 
      begin 
      result.Top := cellrect.Top + ((RowHeight - BTN_WIDTH) div 2); 
      result.Left := result.Left + TXT_MARG.x; 
      result.Bottom := result.Top + BTN_WIDTH; 
      result.Right := result.Left + BTN_WIDTH; 
      end; 
     end; 
    end; 
    end; 

var 
    cellrect: TRect; 
begin 
    result := Rect(0, 0, 0, 0); 

    //Get complete cellrect for the current cell: 
    cellrect := gridOwnerDraw.CellRect(ACol, ARow); 

    //Last visible row sometimes get truncated so we need to fix that 
    if (cellrect.Bottom - cellrect.Top) < gridOwnerDraw.DefaultRowHeight then 
    cellrect.Bottom := cellrect.top + gridOwnerDraw.DefaultRowheight; 

    if ARow > 0 then 
    begin 
    //Additional lines have two buttons: 
    case ACol of 
     1: result := MakeBtnRect(taCenter, cellrect, complete); 
     2: result := MakeBtnRect(taCenter, cellrect, complete); 
    end; 
    end; 
end; 

procedure TForm1.gridOwnerDrawClick(Sender: TObject); 
var 
    where: TPoint; 
    ACol, ARow: integer; 
    btnRect: TRect; 
begin 
    //Again, check to avoid recursion: 
    if not FInMouseClick then 
    begin 
    FInMouseClick := true; 
    try 
     //Get clicked coordinates and cell: 
     where := Mouse.CursorPos; 
     where := gridOwnerDraw.ScreenToClient(where); 
     gridOwnerDraw.MouseToCell(where.x, where.y, ACol, ARow); 
     if ARow > 0 then 
     begin 
     //Get buttonrect for clicked cell: 
     btnRect := GetBtnRect(ACol, ARow, false); 
     InflateRect(btnrect, 2, 2); //Allow 2px 'error-range'... 

     //Check if clicked inside buttonrect: 
     if PtInRect(btnRect, where) then 
     begin 
      case ACol of 
      1: Checked1[ARow]:= Not Checked1[ARow]; 
      2: Checked2[ARow]:= Not Checked2[ARow]; 
      end; 
     end; 
     end; 
    finally 
     FInMouseClick := false; 
    end; 
    end; 
end; 

procedure TForm1.gridOwnerDrawDrawCell(Sender: TObject; ACol, ARow: Integer; 
    Rect: TRect; State: TGridDrawState); 
var 
    txtRect: TRect; 
    btnRect: TRect; 
    btnState: integer; 
    focusRect: TRect; 
begin 
    //If header is to be drawn: 
    if ARow = 0 then 
    begin 
    end 

    //For the rest of the rows: 
    else 
    begin 
    //Setting canvas properties and erasing old cellcontent: 
    gridOwnerDraw.Canvas.Brush.Color := clWindow; 
    gridOwnerDraw.Canvas.Brush.Style := bsSolid; 
    gridOwnerDraw.Canvas.Pen.Style := psClear; 
    gridOwnerDraw.Canvas.FillRect(rect); 

    //Textposition: 
    txtRect := Rect; 
    focusRect := Rect; 
    if ACol = 1 then 
    begin 
     txtRect.Left := Rect.left + BTN_WIDTH + TXT_MARG.x + TXT_MARG.x; 
     focusRect.Left := txtRect.Left; 
    end 
    else if ACol = 2 then 
    begin 
     txtRect.Left := Rect.left + TXT_MARG.x; 
    end; 

    //Drawing selection: 
    gridOwnerDraw.Canvas.Font.Style := []; 
    if (gdSelected in State) then 
    begin 
     gridOwnerDraw.Canvas.Brush.Color := clbtnFace; 
     gridOwnerDraw.Canvas.Font.Color := clBlue; 
    end 
    else 
    begin 
     gridOwnerDraw.Canvas.Brush.Color := clWindow; 
     gridOwnerDraw.Canvas.Font.Color := clWindowText; 
    end; 
    gridOwnerDraw.canvas.FillRect(Rect); 

    //Drawing buttons: 
    if ACol > 0 then 
    begin 
     //Clear buttonarea: 
     btnRect := GetBtnRect(ACol, ARow, true); 
     gridOwnerDraw.canvas.Brush.Color := clWindow; 
     gridOwnerDraw.canvas.FillRect(btnrect); 

     //Get buttonposition and draw checkbox: 
     btnRect := GetBtnRect(ACol, ARow, false); 
     btnState := DFCS_BUTTONCHECK or DFCS_FLAT; 
     if (ACol=1) and Checked1[ARow] then 
     btnState := btnState or DFCS_CHECKED 
     else if (ACol=1) then 
     btnState := btnState or DFCS_BUTTONCHECK 
     else if (ACol=2) and Checked2[ARow] then 
     btnState := btnState or DFCS_CHECKED 
     else if (ACol=2) then 
     btnState := btnState or DFCS_BUTTONCHECK; 
     DrawFrameControl(gridOwnerDraw.canvas.handle, btnRect, DFC_BUTTON, btnState) 
    end; 

    //If selected, draw focusrect: 
    if gdSelected in State then 
    begin 
     gridOwnerDraw.canvas.pen.Style := psInsideFrame; 
     gridOwnerDraw.canvas.pen.Color := clBtnShadow; 
     gridOwnerDraw.canvas.Polyline([Point(focusRect.left-1, focusRect.Top), Point(focusRect.right-1, focusRect.Top)]); 
     gridOwnerDraw.canvas.Polyline([Point(focusRect.left-1, focusRect.Bottom-1), Point(focusRect.right-1, focusRect.Bottom-1)]); 
     if ACol = 1 then 
     gridOwnerDraw.canvas.Polyline([Point(focusRect.left-1, focusRect.Top), Point(focusRect.left-1, focusRect.Bottom-1)]) 
     else if ACol = gridOwnerDraw.ColCount - 1 then 
     gridOwnerDraw.canvas.Polyline([Point(focusRect.right-1, focusRect.Top), Point(focusRect.right-1, focusRect.Bottom-1)]); 
    end; 
    end; 
end; 

end. 
+2

수정하기 전에 문제가 없었습니까? 랜덤 코드 조각의 중요성은 무엇입니까? –

+0

SSCCE를 제공하십시오 –

+0

원래 코드는 상태를 변경하지 않으므로이 문제가 표시되지 않습니다. 전체 코드를 추가했습니다. – user3640611

답변

1

클릭이 체크 상자 경계에 있다고 판단한 후에 페인트를 트리거하지 않기 때문에 두 번의 클릭이 필요합니다. 두 번째 클릭은 이전 셀과 동일 셀인지 여부에 관계없이 이전에 선택한 셀을 무효화합니다. 따라서 스위치가 전환 된 상태가 반영됩니다.

은 다시 칠이 확인란을 무효화 : 당신의 gridOwnerDrawDrawCell은 해당 검사 상태를 그리기 때문에 무효의
procedure TForm1.gridOwnerDrawClick(Sender: TObject); 
var 
    where: TPoint; 
    ACol, ARow: integer; 
    btnRect: TRect; 
begin 
     .. 
     ... 
     if PtInRect(btnRect, where) then 
     begin 
      case ACol of 
      1: Checked1[ARow]:= Not Checked1[ARow]; 
      2: Checked2[ARow]:= Not Checked2[ARow]; 
      end; 
      InvalidateRect(gridOwnerDraw.Handle, @btnRect, True); // <-Here 
     end; 
     end; 
    finally 
     FInMouseClick := false; 
    end; 
    end; 
end; 

를 호출됩니다.

+1

그게 전부입니다. Sertac에게 감사드립니다. – user3640611

관련 문제