TStringGrid で選択された行を知る別の方法 (実際にはこれが唯一の方法です)。
YourstringGrid.Selection.Top;
YourstringGrid.Selection.Bottom;
選択された行が 1 つしかない場合は、それらが一致する必要があります。
YourstringGrid.Row.Selection.···
が選択行の取得に失敗しているように見えるのを見たときに、失敗することはありません。多くの場合、他の値を返さなければならないと思うと -1 が返されます (失敗したように見える理由を理解するには、最後の 4 つのポイントを参照してください。 -1 が返された場合は、実際には失敗ではありません。これは基本的に理解されている概念です)。
選択とフォーカスのあるセルは同じものではありません....Selection
選択用で.Row
あり.Col
、フォーカスのあるセル用であり、選択に関連するものは何もありません。選択がセルの完全に異なる範囲である間、フォーカスのあるセルにすることができます(どちらも異なる概念です)。
YourstringGrid.Row<>YourstringGrid.Selection.Top
また、それが真である可能性があることを発見しました。フォーカスのあるセルが選択範囲の一番上の行にない場合。
インターネットで公開されているいくつかのハック、トリック、コードなどgoRowSelect=False
は、True に設定するとそのようなルーチンがうまく機能しない場合にのみ使用されます。注意して使用してください。
goRowSelect=True
ヒント:複数の行をコードで選択するのは非常にバグが多いTStringGridでは、変更.Selection
しても更新されないことがあります.Row
(フォーカスのある実際のセルは変更されません)。行の値を に直接割り当てる方がよいでしょう.Row
。
覚えておいてください: TStringGrid ではgoRowSelect=True
、どのセルにフォーカスがあるかについて話すことには意味がありません。したがって、それをコーディングするときは、そのようなことをまったく念頭に置いていません (.Row
そして、.Col
いつでも読んではいけませんgoRowSelect=True
)。言い換えれば、常に行全体が選択されている場合、フォーカスのあるセルをチェックする必要がある場合、そのようなセルはなく、行全体であるなど...バグに悩まされないように考えてくださいgoRowSelect=True
TStringGridでフォーカスされたセルを混合するときの内部実装。
また、最悪の場合:goRowSelect=True
いくつかのキーボードの組み合わせ (Shift + カーソル) とマウス クリックを使用すると、列内の 2 つまたは 3 つのセルなどのまれな選択を行うことができますが、行全体を選択することはできません。goRowSelect=True
それがあり、グリッドには選択された行の一部のセルのみが表示されることを覚えておいてください。読む.Selection
と、行のすべてのセルが選択されているわけではないことがわかります(True=(TheGrid.FixedCols+#<TheGrid.Selection.Left)
ここでも、そのようなバグに注意してください...私が言えることは...私は常に選択の変更をトラップし、完全な行をselectectにすることを強制します(すべての選択が常に完全であることを確認するためにOnSelectCellにコードを配置します行/秒)、簡単なコードを参照してください(どのセルが選択されているかは気にしないことに注意してください。概念により、選択はセルではなく行全体または行全体に移動する必要があります。これもまれな概念ですが、内部実装では考えられません選択したセルが変更されたときに何かをしたいので、このイベントにはコードがないはずです。このコードを配置して、選択範囲が完全な行ではないバグを修正します):
procedure TYourForm.YourGridSelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean);
begin
YourGrid.Selection:=TGridRect(Rect(YourGrid.FixedCols,YourGrid.Selection.Top,YourGrid.FixedCols,YourGrid.Selection.Bottom));
end;
単純化: TStringGrid はバグが多すぎ.Selection.Top=2
ます.Selection.Bottom=5
。選択範囲外のアクティブな行をどのようにすることができますか? これは、'.Row' (および も.Col
) が選択された行について話さず、どのセルにフォーカスがあるかについて話しているためです。そのため、.Row
どの行が選択されているかを知ることは概念的に間違っています...フォーカスのあるセルで、実際の選択セルとは関係ありません。
私はこれが失敗するのを見たことがない:
- .Selection.・・・常に選択範囲を教えてくれる(選択中と表示されている範囲)
- .Rowに値が割り当てられている場合(およびグリッドに がある場合
goRowSelect=True
)、その行全体が選択されます( なしで試したことはありませんgoRowSelect=True
)が、1行のみです。
言うまでもなく、TStringGrid を何度もハックして、複数の連続選択を同時に行う複数行の選択 (ListBox の複数選択のように) にしたい場合は言うまでもありません。これは、TStringGrid が .Row および .Selection プロパティの管理に関して持っているすべてのバグのために、事態を非常に混乱させます。
このような複数選択グリッドの場合、TStringGrid の代わりに非公式の VCL コンポーネントを常に使用することをお勧めします。覚えていない場合は、TMultiSelectStringGrid と呼ばれます。その上に、読み取り/である各セル、行、列の .Selected プロパティがあります。書き込み可能。キーを押した状態で複数選択したい場合は本当にうまく機能し、Ctrl複数行選択と複数列選択でもうまく機能します...行、列、またはセルをループして、魔女が選択されていることを確認するだけですそうでないもの。また.RightMouseSelect
、右クリックして選択するプロパティもあり(覚えていない場合)、うまく機能します。
警告、右クリックで選択するすべてのコードが正しいわけではありません...それらの多くは、複数選択があるかどうかを気にしません....Row
複数の行を選択したままにしたい場合は決して設定しないでください。チェックしてください変更前にマウスが選択範囲外にある場合は、そうで.Selection
なければ右クリックで選択を変更できます...したがって、どのようにして複数の行のメニューをポップアップできますか (使用例: 同時に複数のエントリの削除と呼ばれるポップアップ メニュー エントリ時間)。
言い換えれば(VCL標準TStringGridに実際に使用するコード):
procedure TYourForm.YourGridMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
ACol,ARow:Integer;
begin
YourGrid.MouseToCell(X,Y,ACol,ARow);
if goRowSelect in YourGrid.Options
then begin // TStingGrig with full row selected, no individual cell must be selected
if (ARow<YourGrid.Selection.Top)
or
(YourGrid.Selection.Bottom<ARow)
then begin // Where clicked is outside the actual rows that are selected
YourGrid.Row:=ARow;
end;
end
else begin // TStingGrig where individual cells can be selected
if (ARow<YourGrid.Selection.Top)
or
(YourGrid.Selection.Bottom<ARow)
or
(ACol<YourGrid.Selection.Left)
or
(YourGrid.Selection.Right<ACol)
then begin // Where clicked is outside the actual selection
YourGrid.Selection:=TGridRect(Rect(ACol,ARow,ACol,ARow)); // Select the clicked cell
end;
end;
end;
注: 私は実際にユニットのプロシージャにそのコードを持っており、グリッド参照と X、Y 座標を渡してそのプロシージャを呼び出します。私が使用するユニットは TStringGrid の完全なハックであり、 as として宣言されているtype TStringGrid=class(Grids.TStringGrid)
ので、ビジュアル デザインを使用して、それらすべてに余分な機能を追加できます。ユニットリストの最後にあるセクションにそのようなユニットを追加するようにハックが機能することを確認してinterface
uses
ください(または少なくともグリッドの後、決してグリッドの前ではありません)。
ポップアップ メニューを表示するかどうか、およびどのポップアップ メニューを表示するかを制御するための特別なヒント:
- eventで実行し、 onではなく
OnMouseDown
、neverなどで行います。または、選択が変更される前にポップアップメニューが表示されます...そして、選択が(コードによって)変更されると、ポップアップがすぐに非表示になります。OnMouseUp
OnClick
OnMouseDown
ポップアップ メニューを強制的にコードで表示する必要がない場合は、通常どおり表示されます。また、表示されるポップアップをキャンセルすることもできます。たとえば、セル データの外側をクリックした場合、または FixedCols、FixedRows ごとに異なるポップアップを表示したり、セルごとに異なるポップアップを表示したりできます (設計時のポップアップについて説明します。また、表示される前に動的にポップアップ エントリを作成することもできますOnMouseDown
。popup が実行時に作成される場合、同じことを考えてください: で表示するかどうか、独自のメニュー イベントOnMouseDown
でのメニューの構築。OnPopup
基本的なトリックは、イベントOnMouseDown
で選択変更を行うことです。ポップアップ メニューが表示される前に発生します。
ああ、私のコードでは、どのボタンがクリックされたかは気にしません。複数の行が選択されている状態で左クリックすると、通常どおりに動作するからです (私のコードは、選択や行などに変更を加えません。実際には何もしません)。 、if
s) を参照してください) が、選択が 1 行だけに変更されていることがわかります。
注意してください。選択は、マウスを左クリックして保持し、次にマウスを動かして左ボタンを持ち上げることで、複数のセル/行を選択する複数選択に変更することもできます。ユーザーが選択しなければならないこのすべての方法は、標準コンポーネントの内部実装を非常にバグのあるものにし、内部的にコーディングされている間、アクションのすべての組み合わせが考慮されていませんでした。
左マウスが押されている間にandCtrlまたはを押してみてくださいShift。コードをまったく使用せずに標準グリッド上でマウスを動かしています。値が数百万(グリッドには数列しかないため、不可能な値)であると言っていることがありますが、 (「.Col」で失敗した場合とは異なる値)と同じです。.Row
.Col
.Selection.···
.Col
.Row
したがって、返される値を信じないでください。選択.Row
と.Col
は何かを考えている場合は (間違った概念です。それらはどのセルにフォーカスがあるかを表し、選択とは何の関係もありません)。ただし、それらを使用して、1 つの行または列のみを選択することができます (ハッキングされたグリッドを使用する場合は列のみ、またはグリッドを使用goRowSelect=False
して独自の列選択をシミュレートする場合)。
そして、常にこれを念頭に置いてください(常に実行してください):
- フォーカスのあるセル (どれがどれかを教え
.Row
て.Col
くれるかもしれません) は、実際の選択範囲外にある可能性があります。マウスの移動、クリック、およびAlt、Ctrl、Shift、カーソルとの組み合わせSpacebarが発生する可能性があります)。したがって、選択について何も信頼し.Row
たり.Col
、知ったりしないでください (これは概念上間違っています)。常に を使用して.Selection.···
ください。
私がこれを理解するまで私が持っていたように、これが頭を悩ませないのに役立つことを願っています:
.Selection.···
は、選択されたセルの 1 つの長方形領域のみを表します (goRowSelect
が True か False かは気にしません)。
.Selection:=TGrigRect(Rect(Left,Top,Right,Bottom));
実際の選択を別のものに変更する最良の方法です(自分Left<=Right
で確認してください。そうしないとTop<=Bottom
、事態が非常に悪化する可能性があります)。コードをこの巨大なものと考えてください: .Selection:=TGrigRect(Rect(Min(Left,Right),Min(Top,Bottom),Max(Right,Left),Max(Bottom,Top));
(Min
とを参照してください。Max
それらはMaths
ユニット内にあります)。
.Row
点線の長方形が描画されている特別なセルの行番号を返します。セルが選択範囲内にあるか、選択範囲外にあるかに関係なく、セルにフォーカスがない場合は -1 になります。セレクションとは関係ありません。
.Col
点線の長方形が描画されている特別なセルの列番号を返します。セルが選択範囲内にあるか、選択範囲外にあるかに関係なく、セルにフォーカスがない場合は -1 になります。セレクションとは関係ありません。
4 つのことを理解すると、headages が過去のものになる可能性があります。フォーカスのあるセル (「.Row」と「.Col」) と選択されたセル ( ) という 2 つの異なる概念を理解するのに時間がかかりすぎました.Selection.···
。
PD: この情報を自由に共有してください!