Caspar Lee
Caspar Lee

Reputation: 103

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:

  1. 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.
  2. 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

Upvotes: 8

Views: 2403

Answers (2)

peterfelts
peterfelts

Reputation: 552

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.

Upvotes: 2

Simon Rozman
Simon Rozman

Reputation: 327

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.

Upvotes: 0

Related Questions