Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

High DPI bug in LMD Docking Pack 2024

Hi, I believe that this has been an issue for a long time. As more users of our product are using high resolution monitors this problem is getting raised more frequently.

Problem:
The floating panel/window and the glow outline are painted in different positions when the panel is on a monitor with scaling set to something other than 100%.

Scenario:
Run the LMD Docking Demo on a system that has two monitors, primary set to 100% scaling and a second monitor set to 150% scaling.
Drag one of the docked panels out of the main window so that it is floating.
Drag that panel to the secondary monitor with 150% scaling.

Expected:
Glow border is painted in the correct position, as shown here when it is on the primary 100% scaling monitor:

Result:
The glowing border outline is painted in a different position to the panel window, offset horizontally and vertically which  changes depending on where on the monitor the panel is dragged as shown below.
There are also strange glow outlines painted in strange positions while the panel window is visible on both monitors and some strange jumping/movement of the panel window shortly after moving it to a different monitor.

This is a problem both with Delphi 12.2 and 10.1, in both the LMD Docking Demo and in our own application (which is not DPI aware).

I was unable to try LMD Docking Pack 2025 because the download links are broken (see next post).

UPDATE: I tried changing the DPI Awareness manifest setting in the project options of the LMD Docking Demo and found that ONE SETTING WORKS: Per Monitor v2.
If the setting is anything else then the position of the glow/border is incorrect. In our application we use a setting of None.
png
png
Good - 100 Percent Scale Monitor.png
2K
png
png
Bad - 150 percent scale monitor.png
4K

Comments

  • 4 Comments sorted by Votes Date Added
  • When speaking about High DPI support, the DPI Awareness should be set to its default value "Per Monitor v2". I will look what happens in "None" case, but it's obvious, that scaling will not work properly. Look at you second image, the panel itself is not scaled.
  • Hi Eugene,

    Our application has just been migrated from D10.1 to D12.2. In 10.1 the Per Monitor v2 was not available in D10.1 so we didn't encounter it until now. For the first release of our application using D12.2 we won't be able to use Per Monitor v2 due to time constraints solving the various problems that it causes, so we will add full high DPI support in a future release.

    Solving the TGlow DPI issue when DPI awareness is set to anything other than Per Monitor v2 will need to be done in the LMD code. I will investigate but I am running our of time to fix it in this release of our application.

    I tried various solutions without modifying LMD code but some of the required code is local/private and not configurable. e.g. Our form needs to intercept CM_DIALOGKEY for special processing of arrow keys so we use our own TLMDFloatingForm descendant class by setting TLMDDockPanel.FloatingDockSiteClass but there is still a hard-coded TLMDFloatingForm.CreateEx in TLMDDockManager that won't use our descendant floating form class when loading forms from file. It would be nice if it could use a global FloatingDockSiteClass to determine which class to use.

    I thought that I could replace TLMDFloatingForm.CreateWnd using our descendant floating form class and avoid the call to InitGlows. It was possible (but tricky) to avoid calling TLMDFloatingForm.CreateWnd and instead call the inherited TCustomForm.CreateWnd. This introduced a problem. Without the TGlow objects the window resize handles are missing so the window cannot be resized by the user. At that point I gave up trying to remove the TGlow objects.

    I will see if I can find and suggest a fix for the TGlow DPI issue. Thanks for any help that you can provide.
  • Hi Eugene,

    I have done some further investigation. It seems that the problem occurs in TGlow.Update. The scenario is:
    1. Primary monitor has scaling set to 100% and the app main form starts on that monitor
    2. A TLMDFloatingForm window is created from the app on the secondary monitor or is moved from the primary to the secondary monitor. The secondary monitor has scaling set to 150%

    The floating form on the secondary monitor looks ok itself and its position and size are known.

    In TGlow.Update the call to GetBounds returns the correct absolute pixel co-ordinates for the edges of the form, and dpos and sz also contain the correct position and size for the glow windows with no scaling applied. They match the actual window position and size and the glows would be displayed correctly if they were positioned and sized using these values.

    The problem occurs in the call to UpdateLayeredWindow.

    The dpos and sz params contain the correct locations and size but the visible position and size of the TGlow's are scaled by 150%, with the position scaled *relative to the upper left position of the secondary monitor*, not relative to the absolution pixel position of the window. For example, my secondary monitor is to the right of the primary monitor and starts at top left position 1920, -1065 (the second monitor is higher resolution), so the position scaling is relative to that location. If you drag the floating window to the upper left of that monitor (1920, -1065) then the top and left TGlow's are displayed in the correct position (because 0 offset x 150% = 0). If you drag the window 100 pixels to the right the scaling causes the position to increase and the TGlow's drift further away from their correct position, with the left glow at x position 2070 instead of 2020 (100 offset * 150% = 150 + 1920).

    I hacked a quick fix before the call to UpdateLayeredWindow to confirm the calcs:
        if dpos.X >= 1920 {secondary monitor} then
        begin
          dpos.X := MulDiv(dpos.X - 1920, 96, 144) + 1920;
          dpos.Y := MulDiv(dpos.Y - (-1065), 96, 144) + (-1065);
          sz.X := MulDiv(sz.X, 96, 144);
          sz.Y := MulDiv(sz.Y, 96, 144);
        end;

    This solves the position and size but there are still a couple of problems. The glow bitmap at the bottom right corner looks slightly wrong and the diagonal resize handle at the top right and bottom right corners don't work. It also seems that if you drag the floating window up quickly it jumps to a different position (dragging slowly is ok, dragging fast down or horizontally is ok). Obviously the code needs to be adaptive to the position and DPI of any monitor on which the form is displayed and the other issues would need to be investigated.

    Thanks again.
  • All these issues are artefacts of DPI awareness set to None. Windows itself makes some hacks internally in this case, which result in wrong glow appearance. As you writing, coordinates are provided correctly to UpdateLayeredWindow function, but, unfortunately, Windows modifies coordinates internally. This is a kind of workaround for applications which do not support high DPI (do not declare it in its manifest).
Sign In or Register to comment.