forms - 确保例程运行时表单不会获得焦点

标签 forms delphi focus vcl

我有 2 个表单 - 第一个表单有一堆编辑、组合框等,第二个表单有一个 Web 浏览器。

我在第二个表单中有一个例程,它将 HTML 加载到 Web 浏览器中,并且该例程在第一个表单上的所有控件的 OnChange 事件中触发。

问题是,当第二个表单将 HTML 加载到网络浏览器时,我对第一个表单的集中控制失去了焦点。

如何确保例程触发时第二种形式不会获得焦点?或者,更重要的是 - 确保我的第一个表单上的聚焦控件不会失去焦点?

最佳答案

您尝试做的事情违背了VCL,并且可能违背了通常的用户期望:当显示新窗口时,除非它是工具窗口,否则通常(和预期)的行为是将焦点移至它。显示窗口的 Win32 Api 是 ShowWindow并且它将激活窗口,除非指定了 SW_SHOWNOACTIVATE 标志(或其变体之一)。

当您使 VCL 表单可见时,也会调用该函数。对 ShowWindow 的调用隐藏在 procedure TCustomForm.CMShowingChanged(var Message: TMessage) 中,这是一个 135 行的过程,对 SW_SHOWNORMAL 标志进行硬编码(即:激活标志)用于 VCL 进行的 ShowWindow 调用。不幸的是,这是一大段代码,覆盖它并不容易。如果这是我的程序,我可能会尝试更改代码:我会向 TCustomForm 添加一个 DoNotActivate:Boolean 标志并更改CMShowingChanged 中的单行代码为非 MDI 表单调​​用 ShowWindow,以考虑该标志并只需调用 ShowWindow(Handle, SW_SHOWNOACTIVATE)。如果更改 VCL 不是一件轻松的事情,您可以使用以下 hacky 解决方案:

我建议的技巧是创建新表单(包含 TWebBrowser 的表单),但不要将其 Visible 属性设置为 True。相反,手动调用 ShowWindow(Handle, SW_SHOWNOACTIVATE) 来显示表单而不激活它。由于此代码将不再通过通常的 Delphi VCL 进行编码,因此不会自动创建和显示拥有的控件,因此需要对所有 递归调用 ShowWindow(...) TWinControl 形式的后代:

procedure TForm15.Button1Click(Sender: TObject);
var F: TForm16;

  procedure RecursiveShowNoActivate(W: TWinControl);
  var i:Integer;
  begin
    ShowWindow(W.Handle, SW_SHOWNOACTIVATE);
    for i:=0 to W.ControlCount-1 do
      if W.Controls[i] is TWinControl then
        RecursiveShowNoActivate(TWinControl(W.Controls[i]));
  end;

begin
  F := TForm16.Create(Application);
  F.Top := Top + height; // So the new form doesn't overlap mine
  RecursiveShowNoActivate(F);
  F.WebBrowser1.Navigate('http://msdn.microsoft.com/en-us/library/ms123401');
end;

此代码还有一个问题:确保您导航到的网页没有自动聚焦的表单。对于代码示例来说,导航到 Microsoft 的 MSDN 库可能不太常见,但该规范示例 (www.google.com) 将焦点设置在搜索表单上。

关于forms - 确保例程运行时表单不会获得焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6711275/

相关文章:

delphi - DLL 中的 VCL 样式正在影响应用程序中的 TMenuItem

DELPHI Edit.OnExit 通过 TAB,在焦点上显示窗口结果 bug

qt - 识别 QLineEdit 是否失去焦点

python - 单击 `TextInput` 对象后在 Kivy 中重新捕获键盘焦点

xml - 通过DEL上的POST发送和接收XML

javascript - HTML 文本输入选择焦点上的所有内容在 Chrome 中不起作用

javascript - 自动完成表单中的必填输入字段

javascript - 如何在文本输入旁边创建两个垂直堆叠的按钮

Angular - 如何从现有数组启动 FormArray?

javascript - 使用 HTML 表单值进行 AJAX/PHP MySqli 查询