-1

In my experience, I've noticed that there are 3 types of applications:

  1. ones that get along with Windows DPI setting and get scaled correctly.

  2. ones that always keep everything at the same pixel position and don't scale anything (this is what I want).

  3. ones that can't cope with non-standard DPI settings, so their controls are all over the place. Such programs sometimes recommend the user to change their DPI settings.

I already know that there are SetProcessDPIAwareness() and SetProcessDPIAware() functions in the Win32 API, and Scaled and PixelsPerInch properties in the TForm class.

I've experimented with these things, searched the web, but I haven't found or developed any solid approach.

J. Middson
  • 31
  • 3
  • Allow me to disagree: that user is asking about "behaving well". I don't even know what he means by that. You think he means appearing with same size and position regardless of DPI of the system? – J. Middson Jun 17 '17 at 01:28
  • Just to make things clear: the above comment is a reply to Ken White's marking the question as duplicate. – J. Middson Jun 17 '17 at 12:14

1 Answers1

1

To achieve what you desire:

  1. Declare in your application manifest that your program is DPI aware. This will make sure that the system does not scale your program as part of the window composition mechanism.
  2. Set the Scaled property for each form to False. This ensures that the form and its controls are not scaled to the prevailing DPI.

In your application manifest use this setting:

<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <asmv3:windowsSettings
       xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    <dpiAware>True/PM</dpiAware>
  </asmv3:windowsSettings>
</asmv3:application>

It is important to declare the program to be per monitor DPI aware. Otherwise, if you only declare system DPI awareness, then you may still find windows being scaled by the window composition mechanism.

Finally, if you are using Seattle or later, which itself supports per monitor DPI awareness, you need to disable that. It should be enough to override the handling of the WM_DPICHANGED message for each top level window, and do nothing in response to that message:

type
  TBaseForm = class(TForm) // all forms in your program must derive from this base class
  protected
    procedure WMDpiChanged(var Msg: TMessage); message WM_DPICHANGED;
  end;

....

procedure TBaseForm.WMDpiChanged(var Msg: TMessage);
begin
  // return 0 to indicate that we have processed the message
  Msg.Result := 0;
end;
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490