在Delphi 7中使用SetParent将一个C# WinForms窗口嵌入时,键盘输入无法传递到WebView2

后端开发 2026-07-12

我正在把一个现代网页界面集成到一个遗留的Delphi 7桌面应用中,通过托管一个使用WebView2的 C# WinForms可执行程序来实现。

当C#应用独立运行时工作正常。然而,当我通过Windows API SetParent 将它的窗口嵌入到Delphi面板中时,WebView可以正确渲染,但键盘输入无法传达到WebView的文本字段。

鼠标输入可以正常工作,但输入文本无法输入。

症状

在WebView2的聊天输入框中点击时:

  • 文本光标出现在输入框内
  • 鼠标可以正常工作
  • 然而,按键输入的字符会发送给之前获得焦点的Delphi控件,而不是WebView

示例行为:

  1. 点击一个Delphi的编辑框
  2. 点击WebView的输入字段
  3. 输入文本
  4. 文字出现在Delphi的编辑框中,而不是WebView

Delphi:

SetParent(FAgenteHandle, pnlAgenteHost.Handle);

Style := GetWindowLong(FAgenteHandle, GWL_STYLE);
Style := Style and not WS_POPUP;
Style := Style or WS_CHILD or WS_VISIBLE;

SetWindowLong(FAgenteHandle, GWL_STYLE, Style);

SetWindowPos(
  FAgenteHandle,
  0,
  0,
  0,
  pnlAgenteHost.ClientWidth,
  pnlAgenteHost.ClientHeight,
  SWP_NOZORDER or SWP_FRAMECHANGED
);

C#

public partial class Agente : Form
{
    private readonly WebView2 web = new WebView2();

    public Agente()
    {
        InitializeComponent();

        FormBorderStyle = FormBorderStyle.None;
        ShowInTaskbar = false;

        web.Dock = DockStyle.Fill;
        web.TabStop = true;

        Controls.Add(web);
    }

    protected override async void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        await web.EnsureCoreWebView2Async(null);

        web.Source = new Uri("https://example.com");
    }
}

解决方案

根据 跨进程父/子或拥有/被拥有窗口关系是否合法?

...

所以,是的,从技术上讲这是合法的,但如果你创建了跨进程的父/子关系或拥有/被拥有的关系,后果可能非常难以管理。并且当其中一个或两个涉及的窗口并不知情自己正在参与跨进程窗口树时,管理几乎会变得无法管理。 (我常在有人想把属于另一个进程的窗口抓过来强行graft到自己进程的情境下看到这个问题。那个进程对自己的窗口被这样操作根本毫无准备,事情可能会停止工作。 确实,如果你把那个窗口从顶级窗口改成子窗口,事情将肯定停止工作。

...

正确的解决方案应当让Delphi应用完全放弃.NET应用程序,改为为自己创建并托管自己的WebView2对象。例如,可以使用 WebView4Delphi

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章