我有一个 TStringGrid 有几行,我在其中实现了某种“只读”行。更准确地说,我不允许用户单击倒数第二行。如果用户单击最后一行,则没有任何反应;焦点不会移动到该行的单元格。
我有代码(在 KeyDown 中),一切都很顺利。但是,如果用户单击最上面一行,然后使用鼠标滚轮向下滚动,最终焦点将移动到倒数第二行。知道如何防止这种情况吗?
我有一个 TStringGrid 有几行,我在其中实现了某种“只读”行。更准确地说,我不允许用户单击倒数第二行。如果用户单击最后一行,则没有任何反应;焦点不会移动到该行的单元格。
我有代码(在 KeyDown 中),一切都很顺利。但是,如果用户单击最上面一行,然后使用鼠标滚轮向下滚动,最终焦点将移动到倒数第二行。知道如何防止这种情况吗?
好吧,你可以重写DoMouseWheelDown
来实现这一点。
function TMyStringGrid.DoMouseWheelDown(Shift: TShiftState;
MousePos: TPoint): Boolean;
begin
if Row<RowCount-2 then
//only allow wheel down if we are above the penultimate row
Result := inherited DoMouseWheelDown(Shift, MousePos)
else
Result := False;
end;
但是你怎么知道没有其他方法可以将焦点移到最后一行?
事实上,一个更好的解决方案是覆盖SelectCell
:
function TMyStringGrid.SelectCell(ACol, ARow: Longint): Boolean;
begin
Result := ARow<RowCount-1;
end;
当你这样做时,你不需要任何KeyDown
代码,也不需要覆盖DoMouseWheelDown
. 将所选单元格更改为最后一行的所有可能机制都将被此阻止。
正如@TLama 正确指出的那样,您不需要子类TStringGrid
来实现这一点。您可以使用该OnSelectCell
事件:
procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Longint;
var CanSelect: Boolean);
begin
CanSelect := ARow<(Sender as TStringGrid).RowCount-1;
end;
我通过将它放在事件 OnMouseWheelUp 中解决了这个问题:
procedure Tmainform.sgup(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
sg.RowCount := sg.RowCount + 1;
sg.RowCount := sg.RowCount - 1;
end;