How to make hovering over Minimize, Maximize, and Close buttons behave?
Asked Answered
A

1

21

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

  • Minimize
  • Maximize
  • Restore

it doesn't behave correctly:

enter image description here

Compare to an application that does behave correctly:

enter image description here

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:

enter image description here

and in Delphi 5:

enter image description here

and in Delphi 4:

enter image description here

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:

enter image description here

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:

enter image description here

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.

QC Bug Report

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

As you can see: nobody cares.

Agnostic answered 25/7, 2015 at 19:25 Comment(16)
Is this Windows 10? If so, you can't really expect everything to work perfectly using a version of Delphi before the OS was introduced.Murdocca
@Jerry Embarcadero have been marketing heavily that XE8 supports Windows 10 which seems odd to me. I'd be surprised in XE8 behave differently. Also, doesn't Win 10 centre captions?Norge
@David I don't know, haven't seen it yet. I just know those buttons (and entire window style) don't match any version of Windows I've ever seen.Murdocca
@Ian Please let us know what this Windows is. It looks like 8 or later, apart from the left justified captions.Norge
I use Windows 8.1 and still looks far, far from these screenshots. Just tried on Windows 8.1 and everything works as expected.Murdocca
Looking at some screenshots of Windows 10, I'm pretty sure this is in fact the same - and the screenshots I'm looking at have titles aligned to the left (in some but not all). Perhaps there are options to choose this behavior.Murdocca
I have just tested this out on Windows 10 (which does seem to be what OP is using) and it does work as expected. It even works with an old application that was compiled with Delphi 7. So my guess would be that perhaps OP is either running the Windows 10 on an older computer or inside a virtual machine so the Windows detected that the machine might not be powerful enough to run the Windows with decent performance so some of the visual effects might have been disabled.Boise
@IanBoyd if you are running the Windows 10 inside a virtual machine I strongly recommend using WMWare for this. Why? WMWare has good enough drivers for the Guest operating system to actually make use of some hardware acceleration including graphics. So you can even play some of the older games inside the virtual machine if you want. just make sure you have latest WMWare workshop installed since it does support Windows 10 as guest OS and to install WMWare tools inside the Guest operating system.Boise
using Windows 10 pro build 9926 (on VM) it works as expected for Delphi XE8Convertible
@Boise I am running Windows 10 natively on my desktop. And you all are correct, i should wait to a month to ask the question - to ensure that it is not a known issue with Windows. See you in 34 days!Agnostic
I am now running Windows 10 natively. So my question no longer applies to a beta product. And what i would like is someone else to debug to VCL to figure out what it's doing wrong this time. We've had XE6 for a little over a year, and with luck we might be able to ship an application with it next year. Soooo many bugs.Agnostic
@DalijaPrasnikar It works fine with every other application; including Beyond Compare. But here's a Dephi tool, from the mid 1990s, that i didn't write, that was used for maintenance of Paradox tables. It might complain about the BDE not being installed.Agnostic
I have some potentially useful information if someone wishes to tackle this... Our apps are D2007, and we've seen both working and not-working icons. Behaved correctly on Windows 10 inside a VM. But native we can see that the shading flickers as the mouse moves over the button. This leads me to suspect a mouse message is causing the effect to disappear. There is also the possibility that the problem has something to do with graphics drivers.Brophy
It also fails on Microsoft Surface Pro 3 with Windows 10. So it's not just my computer. Fails on two computers, when running on real steel. (and also completely different video card, and completely different "mouse").Agnostic
I've also just testet it with a Delphi 6 application - works perfectly fine. Windows 10 run native.Super
Issue reported as Quality Portal - 11587Staffan
S
10

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;
Staffan answered 6/8, 2015 at 13:4 Comment(6)
A must read: How-To Guide: Upgrading Your Delphi VCL Applications To Support 4K Displays. Follow the link to Alexander Halser's site and download the pdf-tutorial.Varrian
Note: Don't use SetProcessDpiAware in a production environment. It leads to a race condition. The correct way is to use the manifest entry.Agnostic
This solves the problem, although it introduces more. It means that the application now must actually be dpiAware. That's not an easy feat for a lot of applications. And we certainly can't be per-monitor dpiAware; there are many private singletons in the VCL that call GetDeviceCaps(DC, LOGPIXELSY); once at startup. So be sure not to try to manifest for being per-monitor (true/PM) aware.Agnostic
Answer updated with additional information. VCL is source of buggy behavior after all, but I haven't been able to find out where and why. Since this is VCL and not Windows related issue it should be reported to Quality Portal.Staffan
It is worth noting that the issue seems to affect all versions of Delphi going back to at least Delphi 4. (I notice the QC reports says "affects XE4 XE6")Agnostic
While it looks like all versions are affected, when I am reporting issues I put only versions I have tested (in this case I have also included XE6 because that is where you originally have found the issue). AFAIK QA people at Embarcadero will test it on latest version to confirm that issue exists, and whether issue affects previous versions or not is not too much relevant (unless it is plain regression). In issue description I mentioned that issue also exists in Delphi apps made with versions 4, 5 and 7, but those are not listed in QP (the oldest one is 2007).Staffan

© 2022 - 2024 — McMap. All rights reserved.