luebbe 26 Posted September 23, 2020 Hi Folks, I've got two 24" monitors with different resolutions: 2560x1440 -> 122ppi 1920x1080 -> 92ppi Application is set to per-monitor-dpi-v2. Window's scaling is set to 125% on the WQHD monitor. If it is at 100%, the application doesn't get any dpi-change notifications. They should be called "windows scaling change notifications". 😏 When I move the application window between the monitors, there is a lot of flickering going on until all controls are redrawn. Depending on the number of controls, this can take a "while". Is there a way to avoid this visible flickering, in order to get a smoother transition between monitors? Just for laughs: switch your monitor scaling between 100% and 125% with the IDE window open... 😈 Share this post Link to post
pyscripter 694 Posted September 23, 2020 procedure TForm1.FormAfterMonitorDpiChanged(Sender: TObject; OldDPI, NewDPI: Integer); begin LockWindowUpdate(0); end; procedure TForm1.FormBeforeMonitorDpiChanged(Sender: TObject; OldDPI, NewDPI: Integer); begin LockWindowUpdate(Handle); end; 1 2 1 Share this post Link to post
pyscripter 694 Posted September 23, 2020 (edited) 1 hour ago, luebbe said: 1920x1080 -> 92ppi !? Why not 96 to avoid scaling? Edited September 23, 2020 by pyscripter Share this post Link to post
luebbe 26 Posted September 23, 2020 Lovely! Thanks a lot! So I have to live with the delay, which is kind of ok, when there is no more flickering. Maybe I should show a popup "Rescaling form, please wait" 😉 Now I only have to cope with the numerous rounding errors, that make toolbar buttons and other controls shrink over time. Share this post Link to post
Vincent Parrett 764 Posted September 23, 2020 30 minutes ago, pyscripter said: procedure TForm1.FormAfterMonitorDpiChanged(Sender: TObject; OldDPI, NewDPI: Integer); begin LockWindowUpdate(0); end; procedure TForm1.FormBeforeMonitorDpiChanged(Sender: TObject; OldDPI, NewDPI: Integer); begin LockWindowUpdate(Handle); end; I do the same thing when switching themes, but haven't tried this. I wonder how it will go with moving the window from one monitor to the other with different dpi's. At the moment it's terrible, flickers and stops moving for a few seconds. Share this post Link to post
luebbe 26 Posted September 23, 2020 4 minutes ago, pyscripter said: !? Why not 96 to avoid scaling? That value was calculated from monitor size and resolution. The IDE is set to 96 and 96 is stored in the .dfm files. The (Before|After)MonitorDpiChanged methods report changes from 96<->120 dpi (scaling by 1,25). Share this post Link to post
luebbe 26 Posted September 23, 2020 (edited) 43 minutes ago, Vincent Parrett said: I do the same thing when switching themes, but haven't tried this. I wonder how it will go with moving the window from one monitor to the other with different dpi's. At the moment it's terrible, flickers and stops moving for a few seconds. Kiriakos' suggestion works fine. The window is still unresponsive for a few seconds, but at least the flicker is gone. Edited September 23, 2020 by luebbe Share this post Link to post
pyscripter 694 Posted September 23, 2020 There are a number of ways to reduce scaling time: If you are using VirtualLists with many Icons try RtlVclFixes.pas Use ParentFont := True in child controls to avoid scaling fonts For custom components try to fine-tune/override DefaultScalingFlags 1 2 Share this post Link to post
Guest Posted September 23, 2020 49 minutes ago, pyscripter said: Use ParentFont := True in child controls to avoid scaling fonts Of course... had not crossed this feeble mind. Cool! Share this post Link to post
Guest Posted September 23, 2020 2 hours ago, luebbe said: Just for laughs: switch your monitor scaling between 100% and 125% with the IDE window open... 😈 Perhaps add some EULA-like clauses to cover thine behind? Share this post Link to post
luebbe 26 Posted September 23, 2020 Thanks! I just used FixRSP30931.pas (https://quality.embarcadero.com/browse/RSP-30931) which you referenced in RtlVclFixes.pas. I guess I don't need the other fixes with 10.4.1. This cuts down the delay when moving from one monitor to the other by roughly 33%. Share this post Link to post
pyscripter 694 Posted September 23, 2020 42 minutes ago, luebbe said: I guess I don't need the other fixes with 10.4.1. InputBox/Query are still broken. Share this post Link to post
Keesver 23 Posted September 23, 2020 A 'trick' we used to improve the behavior while moving windows between monitors was to create a bitmap when the user starts dragging and use this image while dragging. It works very good and only when the user releases the mouse you need to do rescaling. 1 Share this post Link to post
dummzeuch 1517 Posted September 23, 2020 (edited) 3 hours ago, Vincent Parrett said: LockWindowUpdate Hm, the use of LockWindowUpdate is strongly discouraged by Microsoft: Quote The purpose of the LockWindowUpdate function is to permit drag/drop feedback to be drawn over a window without interference from the window itself. The intent is that the window is locked when feedback is drawn and unlocked when feedback is complete. LockWindowUpdate is not intended for general-purpose suppression of window redraw. Use the WM_SETREDRAW message to disable redrawing of a particular window. Some gotchas of LockWindowUpdate: What does LockWindowUpdate do? And even worse, this describes exactly your use case: With what operations is LockWindowUpdate not meant to be used? Some remarks on WM_SETREDRAW here: The Unfortunate Effect of WM_SETREDRAW No idea whether these still apply, the blog post is from 2011. Edited September 23, 2020 by dummzeuch 1 Share this post Link to post
pyscripter 694 Posted September 23, 2020 (edited) @dummzeuchAll these limitations of LockWindowUpdate are well known and noted. Yes you should avoid using LockWindowUpdate if you can and prefer WM_SETREDRAW. Fully agree. WM_SETREDRAW was the first thing I tried and did not work. As Raymond Chen says in the above articles Quote By now, you’ve probably noticed a common thread to all of these LockWindowUpdate scenarios: They all involve dragging of some sort. Dragging a window caption to move it, dragging the edge of a window to resize it, dragging an item into a window, or dragging an item out of a window. This is not a coincidence. The LockWindowUpdate function was designed with these drag scenarios in mind. Since dragging an item uses the mouse button, and there’s only one mouse, you can’t have multiple drag operations in progress at once, and therefore, there’s no need to lock more than one window for update at a time. The function should perhaps more accurately have been named LockDragWindow. One can well argue therefore, that dragging a Window from one monitor to another is a valid case for using LockWindowUpdate. If it is OK to lock the whole desktop when you do OLE drag&drop it should be OK to lock a single window while dragging it between monitors, just for the time it rescales. Edited September 23, 2020 by pyscripter 4 Share this post Link to post