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

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

问题描述

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




  • 最小化

  • 最大化

  • 还原



它的行为不正确:





与正确行为正确的应用程序进行比较:





重现步骤




  1. 点击文件新建 VCL表单应用程序 - Delphi

  2. 点击运行(F9)

  3. 将鼠标悬停在最小化,最大化或关闭按钮上。

如何修复?




  • Windows 10, 64位(在台式机上本机运行)

  • Delphi XE6



编辑 - 它也失败了Delphi 7:





和Delphi 5:





和Delphi 4:





高DPI是触发器



我终于弄清楚为什么它在每个使用的Windows 10机器上失败;但不是每个人高分辨率。



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



关闭足够的



Dalija的解决方案有效:





我们将忽略该工具提示的问题,并活下去争取一天。



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



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



我们从来没有弄清楚问题是什么;只有在运行多个显示器的用户的路上才踢了它。

解决方案

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



出现此问题的应用程序不是高DPI感知。悬停问题的解决方案是通过使用1,2或3之间的解决方案,使他们知道或打开相关的兼容性模式。



注意:是否将其余的应用程序当高DPI意识被打开是另一个问题,并且将不同于应用程序。


  1. 在兼容模式下检查禁用在高DPI设置上显示缩放


  2. 调用 SetProcessDPIAware 作为 .dpr 文件 - 如Ian Boyd所指出的,调用此函数可以进行竞争条件,首选方式是使用清单。 SetProcessDPIAware


  3. 使用 true true / PM 设置(默认Delphi清单包含启用运行时主题不高DPI意识)


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






 < 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>






更新: / p>

Delphi VCL是错误行为的来源,具体问题在 TForm 类或其祖先的某个地方。当使用直接的Windows API时,结果窗口的行为正常。



Windows API代码行为正常:

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

ShowMessage('Correct'); //如果启用主题 - > Windows任务对话框使用

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



 程序赢; 

{$ R * .res}

使用
Windows,
消息,
SysUtils;

var
消息:TMSG;
LWndClass:TWndClass;
hMainHandle:HWND;

函数WindowProc(HWND,Msg:Longint; wParam:wParam; lParam:lParam):Longint;标准
begin
如果Msg = WM_DESTROY则PostQuitMessage(0);
结果:= DefWindowProc(HWND,Msg,wParam,lParam);
结束

begin
LWndClass.hInstance:= hInstance;
with LWndClass do
begin
lpszClassName:='WinApiWnd';
样式:= CS_PARENTDC或CS_BYTEALIGNCLIENT;
hIcon:= LoadIcon(hInstance,'MAINICON');
lpfnWndProc:= @WindowProc;
hbrBackground:= COLOR_BTNFACE + 1;
hCursor:= LoadCursor(0,IDC_ARROW);
结束

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

而GetMessage(Msg,0,0,0)do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
结束
结束。

不正当的VCL表单:

  var 
f:TForm;

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

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


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

  • Minimize
  • Maximize
  • Restore

it doesn't behave correctly:

Compare to an application that does behave correctly:

Step to Reproduce

  1. Click File, New, VCL Forms Application - Delphi
  2. Click Run (F9)
  3. Hover over the Minimize, Maximize, or Close buttons.

How to fix?

  • Windows 10, 64-bit (running natively on desktop PC)
  • Delphi XE6

Edit - It also fails with Delphi 7:

and in Delphi 5:

and in Delphi 4:

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.

Compatibility Modes

  • 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

Also fails in Skype; also written in Delphi:

High DPI is the trigger

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

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

Close Enough

Dalija's solutions works:

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

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.

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.

解决方案

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

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.

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. Under compatibility mode check "Disable display scaling on high DPI settings"

  2. 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

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

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>

or

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


Update:

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 code that behaves properly:

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

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

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.

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天全站免登陆