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

Memo控件OnExit触发TWebBrowser更新后焦点与光标异常求助

问题原因分析
  • 焦点处理流程冲突:VCL的OnExit事件触发时机处于控件焦点转移的关键阶段,此时VCL正在处理焦点的释放与传递逻辑。而TWebBrowser作为ActiveX控件,调用LoadDocFromString中的Write/Close或Navigate操作会触发ActiveX内部的消息处理,抢占VCL的消息队列,打乱正常的焦点转移流程,导致后续Memo控件无法正确捕获焦点(表现为光标消失、输入异常)。

  • 非VCL控件的焦点特殊性:当从Memo点击TWebBrowser时,焦点转移到了ActiveX容器(非VCL控件),VCL不会立即触发Memo的OnExit事件;直到再次点击Memo2(VCL控件)时,VCL才会补触发Memo1的OnExit,此时在事件中操作TWebBrowser,会打断Memo2正在进行的焦点获取流程,引发异常。

解决方案

避免在OnExit事件中直接执行TWebBrowser的更新操作,改用异步延迟执行的方式,让VCL先完成焦点转移,再处理Web内容更新:

方法1:使用Application.QueueAsyncCall(Delphi 10.2+支持)

在Memo的OnExit事件中,将LoadDocFromString的调用放入异步队列:

procedure TForm1.Memo1Exit(Sender: TObject);
begin
  Application.QueueAsyncCall(
    procedure
    var
      HTMLStr: string;
    begin
      HTMLStr := '<html><body>' + Memo1.Text + '<br>' + Memo2.Text + '</body></html>';
      LoadDocFromString(WebBrowser1, HTMLStr);
    end
  );
end;

procedure TForm1.Memo2Exit(Sender: TObject);
begin
  Application.QueueAsyncCall(
    procedure
    var
      HTMLStr: string;
    begin
      HTMLStr := '<html><body>' + Memo1.Text + '<br>' + Memo2.Text + '</body></html>';
      LoadDocFromString(WebBrowser1, HTMLStr);
    end
  );
end;

方法2:自定义消息 + PostMessage(兼容旧版Delphi)

  1. 定义自定义消息:
const
  UM_UPDATE_WEBVIEW = WM_USER + 1;

type
  TForm1 = class(TForm)
    // ... 控件声明
  private
    procedure UMUpdateWebView(var Msg: TMessage); message UM_UPDATE_WEBVIEW;
  public
    // ...
  end;
  1. 实现消息处理过程:
procedure TForm1.UMUpdateWebView(var Msg: TMessage);
var
  HTMLStr: string;
begin
  HTMLStr := '<html><body>' + Memo1.Text + '<br>' + Memo2.Text + '</body></html>';
  LoadDocFromString(WebBrowser1, HTMLStr);
end;
  1. 在Memo的OnExit事件中发送消息:
procedure TForm1.Memo1Exit(Sender: TObject);
begin
  PostMessage(Self.Handle, UM_UPDATE_WEBVIEW, 0, 0);
end;

procedure TForm1.Memo2Exit(Sender: TObject);
begin
  PostMessage(Self.Handle, UM_UPDATE_WEBVIEW, 0, 0);
end;

额外优化:修正LoadBlankDoc中的逻辑错误

原LoadBlankDoc中的循环条件写反,会导致无限循环,正确写法为:

procedure LoadBlankDoc(WB: TWebBrowser);
begin
  WB.Navigate('about:blank', EmptyParam, EmptyParam, EmptyParam, EmptyParam);
  while WB.ReadyState <> READYSTATE_COMPLETE do
  begin
    Application.ProcessMessages;
    Sleep(10); // 适当增加延迟,降低CPU占用
  end;
end;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 05:45:38