グリッドのセル毎のEnable制御


deldel  2006-12-06 19:32:12  No: 24161

グリッドのセル毎に、そのセルを選択(クリック)できないように
設定することはできないでしょうか?
イメージとしては、StringGrid1.Cells[2, 3].Enabled := False;
のような感じです。


Basser  2006-12-07 00:49:01  No: 24162

Cellsプロパティはオブジェクトを返さないので

>イメージとしては、StringGrid1.Cells[2, 3].Enabled := False;

のような設定はできませんが、個々のセルに情報を持たせることは可能です。
以下を参考にしてみて下さい。

  type
    TForm1 = class(TForm)
      StringGrid1: TStringGrid;
      procedure FormCreate(Sender: TObject);
      procedure FormDestroy(Sender: TObject);
      procedure StringGrid1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
      procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
    private
      FGridDefProc: TWndMethod;
      function GetCellLocked(ACol, ARow: Integer): Boolean;
      procedure SetCellLocked(ACol, ARow: Integer; Value: Boolean);
      procedure GridProc(var Message: TMessage);

      property CellLocked[ACol, ARow: Integer]: Boolean read GetCellLocked write SetCellLocked;
    end;

  var
    Form1: TForm1;

  implementation

  {$R *.DFM}

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    FGridDefProc:= StringGrid1.WindowProc;
    StringGrid1.WindowProc:= GridProc;
  end;

  procedure TForm1.FormDestroy(Sender: TObject);
  begin
    StringGrid1.WindowProc:= FGridDefProc;
  end;

  function TForm1.GetCellLocked(ACol, ARow: Integer): Boolean;
  begin
    Result:= Boolean(StringGrid1.Cols[ACol].Objects[ARow]);
  end;

  procedure TForm1.SetCellLocked(ACol, ARow: Integer; Value: Boolean);
  begin
    if (GetCellLocked(ACol, ARow) <> Value) then
      StringGrid1.Cols[ACol].Objects[ARow]:= TObject(Value);
  end;

  // 右クリックによるセルロックの切替
  procedure TForm1.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  var
    FCoord: TGridCoord;
  begin
    if Button = mbRight then
      with TStringGrid(Sender) do
      begin
        TStringGrid(Sender).MouseToCell(X, Y, FCoord.X, FCoord.Y);
        CellLocked[FCoord.X, FCoord.Y]:= not CellLocked[FCoord.X, FCoord.Y];
      end;
  end;

  // セルのロック状態確認用描画処理
  procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
  begin
    if not(gdFixed in State) then
    begin
      if CellLocked[ACol, ARow] then
      begin
        TStringGrid(Sender).Canvas.Brush.Color:= clBtnFace;
        TStringGrid(Sender).Canvas.Font.Color := clGrayText;
      end
      else
      begin
        TStringGrid(Sender).Canvas.Brush.Color:= clWindow;
        TStringGrid(Sender).Canvas.Font.Color := clWindowText;
      end;

      TStringGrid(Sender).Canvas.FillRect(Rect);
      TStringGrid(Sender).Canvas.TextOut(Rect.Left, Rect.Top, TStringGrid(Sender).Cells[ACol, ARow]);
    end;
  end;

  procedure TForm1.GridProc(var Message: TMessage);
  var
    FCoord: TGridCoord;
  begin
    // 移動先セル番号取得
    case Message.Msg of
      WM_LBUTTONDOWN:
        FCoord:= StringGrid1.MouseCoord(LOWORD(Message.LParam), HIWORD(Message.LParam));

      WM_KEYDOWN:
        begin
          FCoord.X:= StringGrid1.Col;
          FCoord.Y:= StringGrid1.Row;
          // ※VK_HOME, VK_END, VK_PRIOR, VK_NEXT 等は省略しています
          if (Message.WParam = VK_LEFT)  then Dec(FCoord.X) else
          if (Message.WParam = VK_UP)    then Dec(FCoord.Y) else
          if (Message.WParam = VK_RIGHT) then Inc(FCoord.X) else
          if (Message.WParam = VK_DOWN)  then Inc(FCoord.Y)
          else
          begin
            FCoord.X:= -1;
            FCoord.Y:= -1;
          end;
        end;
    else
      FCoord.X:= -1;
      FCoord.Y:= -1;
    end;

    // ロックされたセルの場合は処理を中止
    if (FCoord.X >= 0) and (FCoord.Y >= 0) and CellLocked[FCoord.X, FCoord.Y] then Exit;

    FGridDefProc(Message);
  end;


deldel  2006-12-07 17:54:12  No: 24163

Basserさん、ありがとうございます。
大変参考になり、勉強にもなりました。
(property はコンポーネントの作成にしか使えないと思ってました^^;)
コード量が思ったより多くてちょっと戸惑っていますが、動作は完璧でした。
利用させて頂きたいと思います(まだあまり理解してませんが^^;)。


junki  2006-12-07 19:14:14  No: 24164

> Cellsプロパティはオブジェクトを返さないので

Objects[Col, Row] に nil か nil 以外を設定して、セル毎の情報をもたせることは
できますね。


Basser  2006-12-08 02:17:37  No: 24165

>Objects[Col, Row] に nil か nil 以外を設定して、セル毎の情報をもたせることは
>できますね。

TStringGridにもObejctsプロパティがあったんですね...
参照先は同じだけど、Colsプロパティを使って回りくどい事しちゃいました。(;^_^)


L  2006-12-13 07:24:25  No: 24166

TCustomGridの継承を作る。

1.CellEnabled(Boolean)プロパティを作る。
2.SelectCell をオーバーライドする、
3.SelectCellの戻り値に CellEnabled[Col,Row] を返せばえんじゃね?


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加