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