グリッドのセル毎に、そのセルを選択(クリック)できないように
設定することはできないでしょうか?
イメージとしては、StringGrid1.Cells[2, 3].Enabled := False;
のような感じです。
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;
Basserさん、ありがとうございます。
大変参考になり、勉強にもなりました。
(property はコンポーネントの作成にしか使えないと思ってました^^;)
コード量が思ったより多くてちょっと戸惑っていますが、動作は完璧でした。
利用させて頂きたいと思います(まだあまり理解してませんが^^;)。
> Cellsプロパティはオブジェクトを返さないので
Objects[Col, Row] に nil か nil 以外を設定して、セル毎の情報をもたせることは
できますね。
>Objects[Col, Row] に nil か nil 以外を設定して、セル毎の情報をもたせることは
>できますね。
TStringGridにもObejctsプロパティがあったんですね...
参照先は同じだけど、Colsプロパティを使って回りくどい事しちゃいました。(;^_^)
TCustomGridの継承を作る。
1.CellEnabled(Boolean)プロパティを作る。
2.SelectCell をオーバーライドする、
3.SelectCellの戻り値に CellEnabled[Col,Row] を返せばえんじゃね?
ツイート | ![]() |