You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Active Form多实例异常求助:多个OCX实例仅显示同一对象

解决Active Form OCX多实例共享内置窗体的问题

这问题我之前帮同事排查过类似的,核心原因几乎都是全局/静态变量的误用——你的OCX实例们共享了同一份窗体资源,所以操作任何一个实例都会触发同一个内置窗体。下面是具体的排查和解决步骤:

1. 检查内置窗体的变量作用域

先看你的Active Form单元里,是不是把内置窗体对象声明成了全局变量(比如在interface部分的var块里):

// 错误示例:全局变量导致所有OCX实例共用同一个窗体
var
  InnerDetailForm: TInnerDetailForm;

这种写法会让所有OCX实例共享这个变量,第一个实例创建窗体后,后续实例都会直接复用它。

修正方案:把窗体变量移到Active Form的类内部,作为实例成员——每个OCX实例都会拥有自己独立的窗体对象:

// 正确示例:类私有成员,每个实例独立拥有
type
  TMyActiveForm = class(TActiveForm)
    btnOpenInnerForm: TButton;
    procedure btnOpenInnerFormClick(Sender: TObject);
  private
    FInnerDetailForm: TInnerDetailForm; // 每个实例专属的窗体变量
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

2. 修正窗体的创建与销毁逻辑

确保每个OCX实例创建时初始化自己的内置窗体,销毁时也独立清理:

constructor TMyActiveForm.Create(AOwner: TComponent);
begin
  inherited;
  FInnerDetailForm := nil; // 初始化实例变量
end;

destructor TMyActiveForm.Destroy;
begin
  // 销毁当前实例的内置窗体,不影响其他OCX实例
  if Assigned(FInnerDetailForm) then
    FInnerDetailForm.Free;
  inherited;
end;

procedure TMyActiveForm.btnOpenInnerFormClick(Sender: TObject);
begin
  // 只创建当前OCX实例对应的窗体
  if not Assigned(FInnerDetailForm) then
    FInnerDetailForm := TInnerDetailForm.Create(nil);
  FInnerDetailForm.Show;
end;

3. 额外排查点

如果上面的修改后还是有问题,再检查这两个地方:

  • 全局资源共享:比如数据模块、配置类是不是用了全局实例,导致多个OCX实例共享状态。要改成每个Active Form实例创建自己的资源副本。
  • 事件绑定问题:内置窗体的事件处理函数是不是绑定到了全局过程?要确保事件处理是属于Active Form实例的成员方法。

可以给每个内置窗体的标题加个标识(比如当前OCX实例的Handle值),这样就能直观验证是不是每个实例都打开了独立的窗体:

FInnerDetailForm.Caption := '内置窗体 - 实例Handle: ' + IntToStr(Self.Handle);

内容的提问来源于stack exchange,提问作者Tomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:49:09