Hi David,
I'm reporting a bug of CResizer when used on an HighDPI-Aware dialog.
I'm going to let my app be HighDPI-aware; I've changed its manifest and declared it PerMonitorV2
-DPIAware. After that, Windows sends the WM_DPICHANGED message to my dialogs.
The bug happens when dragging dialogs, in multi-DPI configurations, between screens with different DPIs. If you don't have an HD screen + a 4K screen (like me), you can emulate the effect by setting a different scaling-percentage on the two screens, like 100% on screen 1 and 150% on screen 2.
When you move a dialog between screens, Windows sends the WM_DPICHANGED to the dialog and it automatically resizes it based on the destination screen DPI value. When I say "resizes" I mean a well done resize (each CWnd scaled and font sizes changed) and not the bad/blurred bitmap resize done on non-DPI-aware applications.
Now comes the issue: if the dialog has a CResizer attached, the CResizer will undo the effect leaving the dialog controls with a wrong layout.
I've made a sample (based on your DialogResizing sample) to show it, together with two screenshots to show you what happens when dragging the same dialog from screen1 (100%) to screen2 (150%) with and without CResizer.
I've tried to "pause" CResizer before WM_DPICHANGED message and "resume" it after WM_SIZE completes, but it didn't work; I've also tried to forcibly re-add child controls to CResizer after WM_DPICHANGED, but it failed too...
Hope I've been clear enough to ease your work...
Additional note: the bug happens only when moving an already created dialog from one screen to another (with different DPI/Zoom).
If the dialog is created directly on screen2 (150%) then its layout is correct; it could be because CResizer is initialized after windows have already resized the dialog upon creation.
Last edit: Claudio Nicora 2021-03-04
Hi Claudio,
Unfortunately this is a 'feature' of the way dialogs are rendered on screens with different DPI scaling settings on Windows 10. They are re-arranged in ways that are impractical to predict by something like CResizer.
Fortunately there is an easy work around. We can handle the WM_DPICHANGED message and recreate the dialog. This is the approach the MovieShow sample uses to allow the application to be moved between screens with different DPI screen scaling.
The code used to handle the WM_DPICHANGED message is shown below. The dialog in question is the view window of a docker, so its parent is the DockClient.
Best regards,
David
Yes. I've seen that example but I'm not able to adapt it to my example.
In the example I've attached (based on your DialogResizing sample), the dialog is a modal CDialog based window, without a View.
Destroying it will terminate the app...
I suppose there should be a way to call
::DialogBox()
again, likeCDialog.DoModal()
does, am I right?Hi Claudio
For the DialogResizing sample, the application ends when the dialog is destroyed because OnDestroy calls PostQuitMessage.
You might like to consider making your dialog the view window of a frame, much like the FormDocView sample. The menu, toolbar, and statusbar are all optional, so the appearance of your application need not change. The definition of the dialog in resource.rc could remain largely unchanged, but the style would need to be modified to make the dialog a child window without a caption.
The use of a frame would probably make things easier. Destroying and recreating the dialog while moving it between screens might prove rather problematic unless it is contained within another window such as a frame. You could even choose to keep the statusbar and do away with drawing the gripper in the dialog.
Hope that helps,
David
Hi Claudio,
Try the attached minifest file in place of your current one.
It utilises gdiScaling in place of PerMonitorV2-DPIAware. That should produce a much better result.
Best regards,
David
Hi David, thanks for it.
Will check it out, but I suppose it'll be supported starting from some Win10 version (1809...?).
Anyway, meanwhile, I've subclassed CDialog to properly manage WM_DPICHANGED messages.
Once the message is received, I disable CResizer, let Windows properly resize the dialog (it only changes locations and sizes), then I scale fonts and reactivate CResizer with the new positions.
It works well and I'm satisfied ;)
I've also switched my graphics (icons, bitmaps, ...) to vectorial versions (EMF and SVG), but that's another story.
Once completed I could send you a cleaned up sample of my CDpiAwareDialog if you want to have a look.
Thanks again
Last edit: Claudio Nicora 2021-04-30
Hi Claudio,
The minimum version of the operating system that supports the gdiScaling element is Windows 10 version 1703.
I'd be happy to have a look at your CDpiAwareDialog when it is ready.
Best regards,
David