StringGridで複数行選択するには?

解決


Del  2008-02-04 09:09:37  No: 29633

StringGridで複数行選択はどうするのでしょうか?

Options のgoRowSelectでは、一行だけだし、
goRangeSelect では、範囲選択になってしまいます。
[Shift]キーや[Ctrl]キーで、行飛ばしも可能な選択にしたいのです。

このように書くと、ListViewで実装しなさいと言われそうですが、
当初ListViewで問題なかったのですが、固定カラムの要望がでまして、
(スクロールしても、最初の2列はスクロールしない等)
ListViewでは、固定カラムはできないですよね?

そこで、StringGridに変更した訳です。
ですが、複数行選択できないなんて知りませんでした。
これでは、StringGridに変更した意味が。。。

一番いいのは、ListViewでの固定カラムが実現できれば問題ないのですが。
↑は愚痴ですので。。。(^^;

StringGridで複数行選択の方法を教えてください。
よろしくお願いします。


KHE00221  2008-02-04 09:38:45  No: 29634

連続した複数行は [SHIFT] を押しながらで選択する事が出来ますが

行飛ばしの複数行選択(複数のRect)を選択する事は出来ません

procedure TCustomGrid.Paint;  を見てもらうと分かりますが

Selection : TGridRect に設定されているエリアを gdSelected を見なしているからです。


KHE00221  2008-02-04 10:21:04  No: 29635

[CTRL] で StringGrid1.Selection を累積していきそれを
StringGrid1DrawCellで描画に反映させれば良いわけで

こんな感じで CTRL で  複数エリア指定する事が可能になります

  SelectionRects : TList;

implementation

{$R *.dfm}

//Grids.pas からコピー
function PointInGridRect(Col, Row: Longint; const Rect: TGridRect): Boolean;
begin
  Result := (Col >= Rect.Left) and (Col <= Rect.Right) and (Row >= Rect.Top)
    and (Row <= Rect.Bottom);
end;

procedure TForm2.SelectionClear;
var
    I : Integer;
begin
    for I:=0 to SelectionRects.Count -1 do
    begin
      Dispose(SelectionRects[I]);
    end;
    SelectionRects.Clear;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
    SelectionRects := TList.Create;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    SelectionClear;
    SelectionRects.Free;
end;

procedure TForm2.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
    ARect : ^TGridRect;
    I : Integer;
begin

    if gdSelected in State then
    begin
      StringGrid1.Canvas.Brush.Color := clRed;
      StringGrid1.Canvas.FillRect(Rect);
    end;

    for I:=0 to SelectionRects.Count-1 do
    begin
      ARect := SelectionRects[I];
      if PointInGridRect(ACol,ARow,ARect^) = True then
      begin
        StringGrid1.Canvas.Brush.Color := clRed;
        StringGrid1.Canvas.FillRect(Rect);
      end;
    end;

end;

procedure TForm2.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    if (not (ssCTRL in SHIFT)) and (not (ssSHIFT in SHIFT)) then
    begin
      SelectionClear;
      StringGrid1.Invalidate;
    end;
end;

procedure TForm2.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
    ARect : ^TGridRect;
begin
    if (ssCTRL in SHIFT) or (ssSHIFT in SHIFT) then
    begin
      New(ARect);
      ARect^ := StringGrid1.Selection;
      SelectionRects.Add(ARect);
      StringGrid1.Invalidate;
    end
    else
    begin
      SelectionClear;
      New(ARect);
      ARect^ := StringGrid1.Selection;
      SelectionRects.Add(ARect);
      StringGrid1.Invalidate;
    end;
end;


Del  2008-02-04 10:28:13  No: 29636

KHE00221様、レス有難うございます。

やはり標準機能では無理ですか。。
[Ctrl],[Shift]キー処理をして、自前の選択行リストなるものを用意して
標準描画しない(DefaultDrwaing=False) で地道に描画させるしか
方法は無いのですね?


Del  2008-02-04 10:34:09  No: 29637

KHE00221様、レス有難うございます。
返信書いてる間に、新たなレスが。。。
しかもサンプルまで載せて頂いて有難うございます。
早速、参考にさせていただきます。


Del  2008-02-04 10:58:02  No: 29638

KHE00221様、完璧です。

Selection(TGridRect)を生かしながら実装できるのですね。
私が考えていたのは、行のみ保持する方法だったのですが、
とても勉強になります。

あとは、同じ行でクリックされた場合の選択反転を実装すれば
希望どうりの動作になります。

迅速なレスに感謝です。
本当に有難うございました。


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

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






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