【问题标题】:How to make hovering over Minimize, Maximize, and Close buttons behave?如何使悬停在最小化、最大化和关闭按钮上的行为?
【发布时间】:2015-10-16 07:00:36
【问题描述】:

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

  • 最小化
  • 最大化
  • 恢复

它的行为不正确:

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

复制步骤

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

如何解决?

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

编辑 - Delphi 7 也失败:

在 Delphi 5 中:

在 Delphi 4 中:

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

兼容模式

  • :失败
  • 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(非客户区主题已禁用):有效

Skype

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

高 DPI 是触发因素

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

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

足够关闭

Dalija 的解决方案有效:

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

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

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

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

质量控制错误报告

因为 Bor...Impr...CodeG...Embarca... Idera 的 QC 网站位于付费墙后面,这是bug report: 的副本

如您所见:没人在乎。

【问题讨论】:

  • 这是 Windows 10 吗?如果是这样,您就不能真的期望在操作系统推出之前使用某个版本的 Delphi 一切都能完美运行。
  • @Jerry Embarcadero 一直在大力宣传 XE8 支持 Windows 10,这对我来说似乎很奇怪。我会对 XE8 的不同表现感到惊讶。另外,Win 10 不是中心字幕吗?
  • @David 我不知道,还没看过。我只知道那些按钮(以及整个窗口样式)与我见过的任何版本的 Windows 都不匹配。
  • 我现在在本地运行 Windows 10。所以我的问题不再适用于测试版产品。我希望其他人调试 VCL 以找出它在 this 时间做错了什么。我们已经使用 XE6 一年多了,如果运气好的话,我们明年也许可以用它发布一个应用程序。错误太多了。
  • 问题报告为Quality Portal - 11587

标签: delphi vcl windows-10 delphi-xe6


【解决方案1】:

高 DPI 是触发因素,它会导致解决方案。

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

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

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

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

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

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


  <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 时,结果窗口会正常运行。

正常运行的 Windows API 代码:

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

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

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

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 表单:

var
  f: TForm;

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

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

【讨论】:

  • 必读:How-To Guide: Upgrading Your Delphi VCL Applications To Support 4K Displays。点击 Alexander Halser 网站的链接并下载 pdf 教程。
  • 注意:不要在生产环境中使用SetProcessDpiAware。它leads to a race condition. The correct way is to use the manifest entry.
  • 这解决了问题,虽然它引入了更多。这意味着应用程序现在必须真正 dpiAware。对于许多应用程序来说,这并不是一件容易的事。我们当然不能是每个显示器的 dpiAware; VCL 中有许多私有单例在启动时调用GetDeviceCaps(DC, LOGPIXELSY);。因此,请务必不要试图表现出对 per-monitor (true/PM) 的感知。
  • 答案已更新,包含更多信息。毕竟,VCL 是错误行为的来源,但我一直无法找出在哪里以及为什么。由于这是 VCL 而不是与 Windows 相关的问题,因此应向 Quality Portal 报告。
  • 值得注意的是,该问题似乎影响了至少可以追溯到 Delphi 4 的所有 Delphi 版本。(我注意到 QC 报告说 “影响 XE4 XE6”
猜你喜欢
  • 2016-10-04
  • 2016-03-04
  • 1970-01-01
  • 2011-03-13
  • 2012-12-09
  • 2012-12-16
  • 2013-04-17
  • 2016-05-17
相关资源
最近更新 更多