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 事件提供的目标索引。
备注:内容仅供参考。
