DPI scaling a complete dialog box from resource - winapi

I setup per-monitor DPI scaling in a Win32 app, and my part works fine, however opening up a dialog box created in the resource editor doesn't scale itself (I would think using dialog units, it would).
Is there a way to scale everything from a dialog resource and be compatible with, say, Win8.1, as well as Win10, and even Win7?

Per-Monitor and Per-Monitor (V2) DPI Awareness:
It is recommended that desktop applications be updated to use
per-monitor DPI awareness mode, allowing them to immediately render
correctly whenever the DPI changes. When an application reports to
Windows that it wants to run in this mode, Windows will not bitmap
stretch the application when the DPI changes, instead sending
WM_DPICHANGED to the application window. It is then the complete
responsibility of the application to handle resizing itself for the
new DPI. Most UI frameworks used by desktop applications (Windows
common controls (comctl32), Windows Forms, Windows Presentation
Framework, etc.) do not support automatic DPI scaling, requiring
developers to resize and reposition the contents of their windows
themselves.
You can resize the dialog box in the WM_DPICHANGED message.
case WM_DPICHANGED:
{
LPRECT lpRect = (LPRECT)lParam;
SetWindowPos(hWnd, nullptr, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, SWP_NOZORDER | SWP_NOACTIVATE);
return 0;
}
Updated:
For per-monitor DPI, v2 is the only one that can handle the dialog DPI scale., v1 does not so on WIndows 8.1 and older versions of Window 10, it has to be done manually. Windows 8.1 and older Windows 10, we don't scale controls. So the solution should be just resize the dialog. It has to enumerate all controls and resize them during WM_DPICHANGED if the dialog is not resizable.

Related

Windows ListView LVS_EX_CHECKBOXES and per-monitor DPI awareness

Does anyone know how to get a standard Windows list view control with LVS_EX_CHECKBOXES to redraw correctly when moved between monitors of different resolution when in per-monitor-v2 mode?
Here's how it looks on the hi-dpi monitor:
After dragging window to a lo-dpi monitor the checkbox itself has resized but the row height is wrong:

Make Windows Common Dialogs "Per Monitor DPI-Aware"

I have a program which was created in VS2008 with MFC.
Now I've modified it to make it "Per Monitor DPI-Aware", and it's almost done. I've modified the manifest and handled the WM_DPICHANGE message. But there's still one problem:
I used CFileDialog class to show Open/Save dialogs, and used SHBrowseForFolder function to show folder selection dialog. But all these dialogs are NOT "Per Monitor DPI-Aware", they won't adjust their UI when you move them between monitors with different DPI settings.
I use spy++ to monitor messages of these dialogs, I find they can receive WM_DPICHANGED message but they just don't handle it.
And I've tested the open file dialog in notepad.exe on Windows 10, it worked perfectly.
Does anyone know how can I make these dialogs "Per Monitor DPI-Aware"?
--------EDIT--------
There're two more problems:
When I move a window to a monitor with different DPI, the window resize itself, but the height of it's title bar and title font-size are not changed.
The checkbox controls' box size is not changed either.
I feel these problems may have some kind of connections, but I can't figure it out.
--------SAD NEWS--------
I compiled microsoft's "DPI Tutorial Sample" with VS2013, and it has the same problem.
https://code.msdn.microsoft.com/DPI-Tutorial-sample-64134744
The titlebar (caption bar) can be scaled by calling EnableNonClientDpiScaling which is available on versions of Windows >= the Windows 10 Anniversary Update (1607).
If you want to DPI scale an older dialog that doesn't support per-monitor DPI scaling you can use SetThreadDpiAwarenessContext (with DPI_AWARENESS_CONTEXT_SYSTEM_AWARE or DPI_AWARENESS_CONTEXT_UNAWARE) to have the top-level windows of the dialog scaled by Windows. The dialog might be blurry but it will at least be sized correctly (also only available on >= 1607 builds of Windows 10). The usage pattern is to call this API before opening the dialog and then restore the previous DPI context immediately after calling the API.
According to MSDN the window that processes WM_DPICHANGED message should return 0. However, any MFC window or control you send WM_DPICHANGED will return 0, since thay call the default window procedure for the unknown messages.
Therefore, judging if some window does process WM_DPICHANGED message by testing its LRESULT return value against zero is not accurate.
The window's title bar of a per-monitor DPI aware application doesn't scale when moving across different DPI monitors as documented on MSDN. Unfortunately, non-client area of the window never adjust the DPI.
Calculator and other per-monitor DPI aware Windows native apps have custom title bar drawing, as described here.

How to get multi-monitor resolution in Process_System_DPI_Aware

I am making an addon for Firefox. Firefox is set to Process_System_DPI_Aware. I have handles to the monitors, is it possible to get the correct monitor rect?
All methods I tried so far are giving me the DPI of the primary monitor.
I thought to use LogicalToPhysicalPointForPerMonitorDPI as it says it should work however I don't have a window to give to the function. The second monitor has no windows on it. I'm trying to take a screenshot of that desktop.
Thanks
You are using per-monitor dpi settings but your process is not per-monitor dpi aware. Thus, your secondary monitor has dpi virtualization.
You should perform your screenshot code from a per-monitor dpi aware process.
You can create invisible window, enumerate monitors using EnumDisplayMonitors, get virtualized rects using GetMonitorInfo, move and resize invisible window fullscreen for each monitor, and get real monitor rect using LogicalToPhysicalPointForPerMonitorDPI.

Using Windows 7 Aero to dim or add a color hue to the whole desktop or a specific window

I would like to apply a light greenish or reddish hue to the entire desktop or select application windows using Windows 7 Aero.
Assuming this is this possible with Aero, is it possible with it so I could potentially port my application to XP?
You'd have a create a window that sits on top of the other windows you wish to dim/hue. This window would use the Aero API calls to enable transparency.
For XP, you'd have to copy the contents of the screen to a bitmap, process the bitmap to make it look like you want, and create a window over the top of the other windows showing that bitmap. This technique would also work under Windows 7, but would not allow changes to any underlying windows to show through.

"Use windows xp style dpi scaling" disables automatic auto-hide of taskbar on W7. Workaround?

We noticed that on W7 with DPI set to > 125% or to > 100% with ("Use windows xp style dpi scaling") turned off, our fullscreen mode (which sets the client rect of our window = desktop rect of the main monitor) no longer hides the task bar like it does for other settings.
(The setting can be found in the Control Panel\Appearance and Personalization\Display section after clicking on the "Set custom text size (DPI)" link)
I found the following interesting article:
http://www.mathies.com/weblog/?p=908
So I set out to try to work around the bug in other means than manually hiding/restoring the taskbar visibility but so far I've failed and currently believe it's a bug in W7 (and possibly vista).
The following applications also fail to work properly in fullscreen mode (the taskbar is still visible):
* Microsoft Visual Studio 2008
* Microsoft Word 2007
* Adobe Reader 9.1.3
These apps work (probably by hiding the task bar through the WIN32 API):
* Powerpoint Slide Show
I also tried creating a brand new MFC-based app and use its "SetFullScreenMode()" functionality but it fails in the same way as all other apps on the list.
For now it seems the only temporary fix which has worked for me is to disable display scaling on high DPI settings for the program your using fullscreen with.
To do this goto properties (right-click the program's shortcut) >> compatability >> and check the option to disable display scaling on high DPI settings.
The only drawback is that you will not get the higher DPI for that program but the taskbar should hide when fullscreen is enabled.
This is a problem that I understand Windows 7 developers are aware of but have not come out with a solution.

Resources