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.

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • 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. – Jerry Dodge Jul 25 '15 at 19:25
  • @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? – David Heffernan Jul 25 '15 at 19:29
  • @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. – Jerry Dodge Jul 25 '15 at 19:37
  • @Ian Please let us know what this Windows is. It looks like 8 or later, apart from the left justified captions. – David Heffernan Jul 25 '15 at 19:44
  • I use Windows 8.1 and still looks far, far from these screenshots. Just tried on Windows 8.1 and everything works as expected. – Jerry Dodge Jul 25 '15 at 19:44
  • 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. – Jerry Dodge Jul 26 '15 at 00:43
  • 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. – SilverWarior Jul 26 '15 at 14:22
  • @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. – SilverWarior Jul 26 '15 at 14:25
  • using Windows 10 pro build 9926 (on VM) it works as expected for Delphi XE8 – zdzichs Jul 27 '15 at 10:53
  • @SilverWarior 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! – Ian Boyd Jul 27 '15 at 14:38
  • 3
    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. – Ian Boyd Jul 30 '15 at 23:01
  • @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](http://s000.tinyupload.com/index.php?file_id=96774342698107193762). It might complain about the BDE not being installed. – Ian Boyd Aug 03 '15 at 13:47
  • 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. – Disillusioned Aug 03 '15 at 15:31
  • 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"*). – Ian Boyd Aug 03 '15 at 22:20
  • I've also just testet it with a Delphi 6 application - works perfectly fine. Windows 10 run native. – Jens Borrisholt Aug 04 '15 at 19:41
  • 2
    Issue reported as [Quality Portal - 11587](https://quality.embarcadero.com/browse/RSP-11587) – Dalija Prasnikar Aug 07 '15 at 08:15

1 Answers1

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;
Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
  • A must read: [How-To Guide: Upgrading Your Delphi VCL Applications To Support 4K Displays](http://community.embarcadero.com/index.php/blogs/entry/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. – LU RD Aug 06 '15 at 15:57
  • Note: Don't use `SetProcessDpiAware` in a production environment. It [leads to a race condition. The correct way is to use the manifest entry](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633543(v=vs.85).aspx). – Ian Boyd Aug 06 '15 at 17:21
  • 1
    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. – Ian Boyd Aug 06 '15 at 17:30
  • 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. – Dalija Prasnikar Aug 06 '15 at 20:26
  • 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"*) – Ian Boyd Aug 07 '15 at 18:33
  • 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). – Dalija Prasnikar Aug 07 '15 at 19:11