delphi - 如何使表单可见并最大化以填充辅助监视器而不激活它?

标签 delphi winapi delphi-xe2

我有一个专为多个显示器设计的应用程序。它启动时,我们尽量避免激活不需要激活的窗口,因为用户只在一个地方进行键盘输入,每次我们在辅助监视器上激活一个新表单时,它都会捕获键盘焦点,这是我们所需要的希望避免。

我们内部的 TForm 基类有一个这样的方法,它直接使用 Win32 ShowWindow 函数,避免了 VCL 框架的内部可见性更改系统来获取焦点:

procedure TOurForm.ShowWithoutActivate;
begin
    ShowWindow(Self.Handle, SW_SHOWNOACTIVATE);
    Self.Visible := true;
end;

如果我这样做,它会捕获焦点:

 Self.Visible := true; // TWindow.Visible = true, will grab focus, plus make window visible.

这可行,但我想做的下一件事是设置最大化状态,以便 表单将在当前所在的监视器上最大化。我们如何将其放到特定的显示器上?与以往的工作方式相同,修改表单的 Left 和 Top 属性。我们必须注意,如果我们将 Left/Top/Width/Height 存储在表单上,​​然后恢复它,那么当我们重新加载它时,结果仍然有效。这不是我要问的。

既然我已经使用上面的自定义函数“显示”了它,我特别询问如何最大化表单。一次黑客攻击会引发另一次黑客攻击。这是我在这个兔子洞里走了多远:

  • 当 TForm(也是 TWinControl 的私有(private)字段 FShowing)为 false 时,设置 Form.Maximized 无效。
  • 当 TForm 的 TWinControl.FShowing 字段设置为 true 时,将 windowState 设置为 wsMaximized 也会导致表单激活。

是否可以使该表单可见并使其采用我希望它在不激活的情况下采用的窗口状态?如果我不能做到这一点,那么当我在辅助显示器上显示此表单时,用户将失去键盘焦点,这是我真正想避免的。

我尝试的是使用Win32 ShowWindow API来执行SW_SHOWMAXIMIZED:

  ShowWindow(Self.Handle, SW_SHOWMAXIMIZED);

以上内容似乎捕获了焦点(激活)。

最佳答案

创建顶级窗口时将扩展窗口样式设置为

WS_EX_NOACTIVATE | WS_EX_APPWINDOW

WS_EX_NOACTIVATE 停止窗口激活。这也会使其从任务栏消失,因此您需要 WS_EX_APPWINDOW 来解决该问题。

调用ShowWindow(hWnd, SW_MAXIMIZE),窗口将最大化但不会激活。

您需要能够在窗口可见后将其激活,因此在 WM_ACTIVATE 处理程序中(讽刺!)您需要清除 WS_EX_NOACTIVATE 标志,如下所示:

case WM_ACTIVATE:
    {
        DWORD exstyle = GetWindowLong(hWnd, GWL_EXSTYLE);
        if (exstyle & WS_EX_NOACTIVATE)
        {
            SetWindowLong(hWnd, GWL_EXSTYLE, exstyle & ~(DWORD)WS_EX_NOACTIVATE);
        }
    }

对 C++ 表示歉意。这应该很容易翻译成 Delphi。

关于delphi - 如何使表单可见并最大化以填充辅助监视器而不激活它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20548321/

相关文章:

windows - Windows 7 上的 DataSnapXE2 正常断开连接

delphi - 我可能在 Delphi XE2 中破坏了什么?

class - 是否可以使用接口(interface)部分的实现部分中声明的类

delphi - 将枚举与泛型一起使用

windows - 如何获得写入注册表项的权限?

.net - 在 Delphi 程序中托管 .NET 运行时

delphi - 如何隐藏对象的 protected 过程?

Delphi firemonkey进程间通信有可能吗?

delphi - 在 Lazarus/Delphi 中修改文件 ACL

c++ - 为什么结构可以存储自己的大小?