如何使悬停在最小化、最大化和关闭按钮上的行为? [英] How to make hovering over Minimize, Maximize, and Close buttons behave?

查看:16
本文介绍了如何使悬停在最小化、最大化和关闭按钮上的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Delphi 应用程序中,当您将鼠标悬停在边框图标上时,例如:

In a Delphi application, when you hover over a border icon, e.g.:

  • 最小化
  • 最大化
  • 恢复

它的行为不正确:

与运行正常的应用程序进行比较:

Compare to an application that does behave correctly:

  1. 点击文件新建VCL Forms Application - Delphi
  2. 点击运行 (F9)
  3. 将鼠标悬停在最小化"、最大化"或关闭"按钮上.

如何解决?

  • Windows 10,64 位(在台式电脑上本地运行)
  • 德尔福 XE6

编辑 - Delphi 7 也失败:

Edit - It also fails with Delphi 7:

在 Delphi 5 中:

and in Delphi 5:

在 Delphi 4 中:

and in Delphi 4:

我假设(即害怕)它是由 ThemeServices 引擎引起的;他们可能认为不尊重用户的偏好很酷.但看起来这是更基本的东西.

I assumed (i.e. was afraid) that it was caused by the ThemeServices engine; where they might have thought it was cool to not honor the user's preferences. But looks like it's something more fundamental.

  • :失败
  • Windows 8:失败
  • Windows 7:失败
  • Windows Vista(Service Pack 2):失败
  • Windows Vista(Service Pack 2):失败
  • Windows Vista:失败
  • Windows XP (Service Pack 3)(非客户区主题已禁用):有效
  • Windows XP (Service Pack 2)(非客户区主题已禁用):有效
  • Windows 98/Windows Me(非客户区主题已禁用):有效
  • Windows 95(非客户区主题已禁用):有效
  • none: fails
  • Windows 8: fails
  • Windows 7: fails
  • Windows Vista (Service Pack 2): fails
  • Windows Vista (Service Pack 2): fails
  • Windows Vista: fails
  • Windows XP (Service Pack 3) (non-client area theming disabled): works
  • Windows XP (Service Pack 2) (non-client area theming disabled): works
  • Windows 98 / Windows Me (non-client area theming disabled): works
  • Windows 95 (non-client area theming disabled): works

在 Skype 中也失败了;也是用 Delphi 编写的:

Also fails in Skype; also written in Delphi:

我终于弄清楚了为什么它在我使用过的每台 Windows 10 机器上都失败了;但并不适合所有人.高 dpi.

I finally figured out why it fails on every Windows 10 machine i've used; but not for everyone. High dpi.

将 dpi 设置为 97 (101%) 或更高.

Set your dpi to 97 (101%) or higher.

Dalija 的解决方案有效:

Dalija's solutions works:

我们将忽略工具提示的问题并继续战斗.

We'll ignore the problem with the tooltip and live to fight another day.

还应该注意的是,Windows 10 会建议您在更改 DPI 后可能必须注销并重新登录才能使某些应用程序正常工作.Delphi 绝对是这样.

It should also be noted that Windows 10 will suggest that you might have to sign off and sign back on for some applications to work correctly after changing the DPI. This is definitely true of Delphi.

还应该注意的是,Delphi 不会容忍 DPI 像这样在其背后发生变化.这包括调整 缩放 滑块.这还包括将应用程序放置在除主显示器之外的任何显示器上.

It should also be noted that Delphi doesn't tolerate the DPI changing behind its back like this. This includes adjusting the zoom slider. This would also include placing the app on any monitor besides the primary monitor.

而且我们从来没有弄清楚问题是什么;只为运行多台显示器的用户踢了它.

And we never did figure out what the problem is; only kicked it down the road for users running multiple monitors.

因为 Bor...Impr...CodeG...Embarca... Idera 的 QC 网站位于付费墙后面,这里是 错误报告:

Because Bor...Impr...CodeG...Embarca... Idera's QC site is behind a pay-wall, here's a copy of the bug report:

如您所见:没人在乎.

推荐答案

高 DPI 是触发器,它会导致解决方案.

High DPI is the trigger and it leads to the solution.

出现此问题的应用程序无法识别高 DPI.悬停问题的解决方案是通过使用 1、2 或 3 下的解决方案之一,让他们知道或打开相关的兼容模式.

Applications that exhibit the issue are not High DPI aware. Solution to hovering problem is to make them aware or turn on associated compatibility mode by using one of solutions under 1, 2 or 3.

注意:打开高 DPI 感知时,应用程序的其余部分是否会正常运行是另一个问题,并且会因应用程序而异.

Note: whether will rest of the application behave properly when High DPI awareness is turned on is another issue and will differ from application to application.

  1. 在兼容模式下勾选在高 DPI 设置下禁用显示缩放"

  1. Under compatibility mode check "Disable display scaling on high DPI settings"

调用 SetProcessDPIAware 作为 .dpr 文件中的第一个调用 - 正如 Ian Boyd 所指出的,调用此函数可能会导致竞争条件,首选方法是使用清单.SetProcessDPIAware

Call SetProcessDPIAware as first call in .dpr file - as noted by Ian Boyd, calling this function can leat to race condition and preferred way is using manifest. SetProcessDPIAware

使用带有 truetrue/PM 设置的自定义清单(启用运行时主题"中包含的默认 Delphi 清单不支持高 DPI)

Use custom manifest with true or true/PM setting (default Delphi manifest included with "Enable runtime themes" is not high DPI aware)

当前版本的 Delphi VCL 和 FMX 框架缺乏对每个监视器 DPI 感知的支持,因此只有在您自己处理每个监视器 DPI 时才使用 true/PM 清单.向 QP 报告为 VCL 和 FireMonkey 缺乏对 Windows 8.1(和 Windows 10)的 Per-Monitor DPI 支持

Current versions of Delphi VCL and FMX frameworks lack support for per monitor DPI awareness, so use true/PM manifest only if you are handling per monitor DPI yourself. Reported to QP as VCL and FireMonkey lack Per-Monitor DPI support for Windows 8.1 (and Windows 10)

  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>

  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true/PM</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>

<小时>

更新:

Delphi VCL 是错误行为的来源,具体问题是 TForm 类或其祖先中的某处.当使用直接 Windows API 时,结果窗口会正常运行.

Delphi VCL is source of buggy behavior, specifically issue is somewhere in TForm class or its ancestors. When direct Windows API is used resulting windows behave normally.

正常运行的 Windows API 代码:

Windows API code that behaves properly:

  MessageBox(0, 'Correct', 'Caption', MB_OK); 

  ShowMessage('Correct'); // if themes are enabled -> Windows Task dialog is used

不使用 VCL 创建主窗口的完整 Delphi 示例应用程序 - 行为正常

Full Delphi sample app that creates main window without using VCL - behaves properly

program win;

{$R *.res}

uses
  Windows,
  Messages,
  SysUtils;

var
  Msg: TMSG;
  LWndClass: TWndClass;
  hMainHandle: HWND;

function WindowProc(HWND, Msg: Longint; wParam: wParam; lParam: lParam): Longint; stdcall;
begin
  if Msg = WM_DESTROY then PostQuitMessage(0);
  Result := DefWindowProc(HWND, Msg, wParam, lParam);
end;

begin
  LWndClass.hInstance := hInstance;
  with LWndClass do
    begin
      lpszClassName := 'WinApiWnd';
      Style := CS_PARENTDC or CS_BYTEALIGNCLIENT;
      hIcon := LoadIcon(hInstance, 'MAINICON');
      lpfnWndProc := @WindowProc;
      hbrBackground := COLOR_BTNFACE + 1;
      hCursor := LoadCursor(0, IDC_ARROW);
    end;

  RegisterClass(LWndClass);
  hMainHandle := CreateWindow(LWndClass.lpszClassName, 'Window Title', WS_CAPTION or WS_MINIMIZEBOX or WS_SYSMENU or WS_VISIBLE, 0, 0, 360, 200, 0, 0, hInstance, nil);

  while GetMessage(Msg, 0, 0, 0) do
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
end.

行为不端的 VCL 表单:

Misbehaved VCL forms:

var
  f: TForm;

  f := CreateMessageDialog('Broken', mtWarning, mbOKCancel, mbOk);
  f.ShowModal;
  f.Free;

  f := TForm.Create(nil);
  f.ShowModal;
  f.Free;

这篇关于如何使悬停在最小化、最大化和关闭按钮上的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆