Delphi Delphi VCL Applications with mixed DPI

FireWind

Свой
Регистрация
2 Дек 2005
Сообщения
1,957
Реакции
1,199
Credits
4,009
Delphi VCL Applications with mixed DPI
Для просмотра ссылки Войди или Зарегистрируйся by Uwe Raabe

High DPI display and 4K Monitors are getting more common these days. Supporting higher settings than 96 dpi is already possible with some of the newer Delphi versions.

Nevertheless this is still a time and resource consuming task. Not only do you need additional sizes for the icons used in your application, you also have to check each form and frame for looking good in higher scaled environments.

A couple of Delphi applications, if not even most, consist of several forms – often there are hundreds of them. This number alone establishes a lower bound for the time required doing checks and tweaks when necessary. Especially in teams with a short release cycle (say 2 – 4 weeks) it means that this may have to be done in a long running feature branch. As a significant part of the work is fiddling around with the form files (dfm), often accompanied by restructuring the controls, this most likely leads to hard to resolve merge conflicts when the main development also tackles these forms.

There are several ways to solve this dilemma. The simplest one is to handle one form or groups of forms sequentially and release each change within the normal release cycle. The application is then kept non DPI aware until all forms are done. This should be accompanied by special builds with high DPI active given to testers only to avoid a nearly blind-folded development. Problems will arise and it is far better to find them early.

A drawback of this approach is that the testers will see all the non-handled forms probably containing high DPI artefacts, which may even render the form unusable. At best this may produce a lot of superfluous bug reports, while at worse it can demotivate the testers.

The better approach is to have all of these later-to-be-handled forms displayed in a non DPI aware way until it is the forms turn to be done properly. For this we need something like a mixed DPI VCL application. Fortunately such thing is possible – at least in systems running Windows 10 version 1607 or higher.

For a practical demonstration we fire up Delphi 10.4.2 and create a fresh VCL Forms Application. Per default the application should have the DPI support set to Per Monitor v2 in its manifest. If that is not the case, make sure it is.

The goal we want to achieve is to have a main form with two buttons and a second form dynamically created on each button click. One of the buttons creates the form just as usual, so the form will take the DPI awareness of the application. The other button creates another form instance from the same form class in DPI unaware mode (i.e. 96 DPI).

So we first add a second VCL form to the application and drop some controls on to it, so we can distinguish the form instances by its display quality on a high DPI monitor. I just assume that the second form class is named TForm2.

Now we get back to the first form and drop two buttons on the form and double click each to fill their event handlers. The first button gets the single line:
Код:
procedure TForm1.Button1Click(Sender: TObject);
begin
  TForm2.Create(Self).Show;
end;
Make sure that the unit containing TForm2 is added to the uses clause.

The OnClick event of the second button needs a bit more code:
Код:
procedure TForm1.Button2Click(Sender: TObject);
var
  previousDpiContext: DPI_AWARENESS_CONTEXT;
  myForm: TForm;
begin
  previousDpiContext := SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
  try
    myForm := TForm2.Create(Self);
  finally
    SetThreadDpiAwarenessContext(previousDpiContext);
  end;
  myForm.Show;
end;
So we temporarily change the DPI awareness of the current thread to unaware, create the form and restore the context to its previous state before finally showing the form.

Now we run this application and click the buttons. Each time a new form is shown with high DPI support or without depending on the button clicked. All forms live happily side by side in our still high DPI aware application.

Note, that we only switch context while creating the form. After that the DPI awareness is bound to that form instance and doesn’t affect others.

The advantage of this mixed DPI approach is, besides the sanity of the testers, that you can even release the application in high DPI mode to the public, of course with the limitation of some forms not being shown in high resolution. The latter should not really be a problem, because the alternative would be to have all forms shown that way. The wider audience will surface errors earlier and people are able to notice the progress.