PAYATHON 2026

Delphi TTabControl 的 OnChanging 中如何获取目标 TabIndex?

数据小许

结论

按题目中的事件声明,假设使用 VCL Vcl.ComCtrls.TTabControl:OnChanging 事件会提供 AllowChange,但事件参数不包含即将选中的标签索引。事件触发时,TabIndex 仍指向当前选中的标签;该事件也没有可供读取目标索引的公开属性。

因此,如果要在切换前根据目标标签决定是否放行,单靠这个事件无法可靠地判断目标索引。Windows 原生通知 TCN_SELCHANGING 同样只表示选择即将变化,不会携带目标索引。可参考 Embarcadero 的 OnChanging 文档 和 Microsoft 的 Tab Control 文档。

现有回退方式

如果可以接受先切换、再恢复旧标签,可以保存切换前的索引,并在 OnChange 中回退。下面的示例加入了重入保护,避免恢复索引时再次执行回退逻辑:

private
  FPreviousTabIndex: Integer;
  FRestoringTab: Boolean;

procedure TForm1.MyTabControlChanging(Sender: TObject;
  var AllowChange: Boolean);
begin
  if not FRestoringTab then
    FPreviousTabIndex := MyTabControl.TabIndex;
end;

procedure TForm1.MyTabControlChange(Sender: TObject);
begin
  if FRestoringTab then
    Exit;

  if (MyTabControl.TabIndex = 3) and MustBlockLastTab then
  begin
    FRestoringTab := True;
    try
      MyTabControl.TabIndex := FPreviousTabIndex;
    finally
      FRestoringTab := False;
    end;
  end;
end;

将 MustBlockLastTab 替换为实际条件。这种做法是在切换后补救:相关的 OnChange 处理可能已经运行。如果切换会触发数据提交、页面初始化等副作用,应确保这些处理能够应对回退。

如果必须在切换前阻止

需要调整交互方式,让程序在切换前就知道用户要进入哪个标签。例如,可以通过明确的按钮或菜单触发切换,并在设置 TabIndex 前检查目标索引;也可以在条件不满足时,不提供该标签的入口。这样就能在当前标签改变前完成判断。

仅凭 OnChanging 中的当前 TabIndex,无法判断用户准备切换到哪个标签。原生控件的焦点索引也不能作为普遍可靠的目标值,因为焦点状态不等同于该 VCL 事件提供的目标索引。

备注:内容仅供参考。