在高dpi显示器上,应用程序缩放了两倍

时间:2019-07-05 16:24:04

标签: c++ winapi dpi

我正在开发一个可识别dpi的winapi应用程序,但遇到一个问题,即无缘无故将其窗口缩放了两倍。似乎在创建应用程序窗口后两次应用了dpi缩放。这是我的代码。 首先,我使我的应用程序能够感知dpi:

::SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);

然后我计算显示器的dpi比例,并考虑此比例创建一个500 x 500的窗口:

dpiScale = <get dpi scale using ::GetDpiForMonitor()> / 96.f;
hWnd = ::CreateWindow(..., 0, 0, 500 * dpiScale, 500 * dpiScale, ...);

我还希望窗口的最小大小为500 x 500:

case WM_GETMINMAXINFO:
{
    MINMAXINFO* info = (MINMAXINFO*)lParam;
    info->ptMinTrackSize.x = 500 * dpiScale;
    info->ptMinTrackSize.y = 500 * dpiScale;
    break;
}

然后我实现dpi更改事件处理:

case WM_DPICHANGED:
{
    dpiScale = LOWORD(wParam) / 96.f;
    RECT rect = *(RECT *)lParam;
    ::SetWindowPos(... rect ...);
    break;
}

当我在高dpi的显示器上启动应用程序时,例如120(x1.25比例因子),应用程序窗口看起来比应有的大。我还尝试在每个WM_SIZE消息上打印出窗口大小:

case WM_SIZE:
{
    RECT r;
    ::GetWindowRect(hWnd, &r);
    int width = (r.right - r.left);
    int height = (r.bottom - r.top);
    std::cout << "WM_SIZE " << width << " " << height << " scale factor: " << (width / 500.f) << std::endl;
    break;
}

这就是我得到的:

WM_SIZE 625 625 scale factor: 1.25
WM_SIZE 781 781 scale factor: 1.562

请注意,只有两个地方可以手动应用dpi缩放:窗口创建和WM_GETMINMAXINFO消息处理。我还尝试从::CreateWindow()通话中删除dpi缩放比例,但它没有任何改变。

尽管我已经为应用程序设置了dpi意识,但是Windows似乎正在自动调整窗口大小。为什么会这样?我该如何解决?谢谢。

已更新

我创建了一个最小的可复制示例,可以在这里找到: https://gist.github.com/APodlinny/179b90b9e0d45ea9576d33dca2273dce 您可以使用摘要中的MSVC项目文件,也可以创建一个空的Win32 MSVC项目,添加main.cpp源文件并确保: *使用Windows SDK 8.1或更高版本(检查项目设置中的VC目录,即包含目录和库目录) * shcore.lib库在链接器中具有其他依赖关系 *链接器子系统为Console

  

也许在Windows 10中为应用程序启用了高dpi缩放?

我对此表示怀疑,因为我在_tWinMain(...)函数的开头为应用程序明确设置了dpi意识。该应用程序兼容性设置中的“覆盖dpi缩放”选项也未选中。此外,窗口内容本身似乎也没有缩放。

  

主监视器与您的应用所在的监视器之间在缩放比例上是否有所不同?

是的,但是我认为这并不重要。我有两个监视器,并且已经以两种配置测试了我的应用程序: 1.在辅助监视器上创建辅助125%,主要100%窗口。 2.在主要监视器上创建次要125%,主要125%的窗口。 在这两种情况下,窗口都会缩放两次。

  

错误在其他代码中。将断点放在::GetWindowRect(hWnd, &r);处理程序中的WM_SIZE上。启动调试器,当它在断点处停止时,使其再次运行。当它第二次停止时,检查调用堆栈以查找第二个WM_SIZE的起源。

感谢提示!看来第二条WM_SIZE消息是Windows发送的WM_WINDOWPOSCHANGED消息引起的:

case WM_WINDOWPOSCHANGED:
{
    WINDOWPOS* pos = (WINDOWPOS*)lParam;
    std::cout << "WM_WINDOWPOSCHANGED " << pos->x << " " << pos->y << " " << pos->cx << " " << pos->cy << std::endl;
    return DefWindowProc(hWnd, message, wParam, lParam);
}
WM_WINDOWPOSCHANGED 100 100 625 625
WM_SIZE 625 625 scale factor: 1.25
WM_WINDOWPOSCHANGED 100 100 781 781
WM_SIZE 781 781 scale factor: 1.562

第一对WM_WINDOWPOSCHANGED / WM_SIZE是由::ShowWindow()引起的,第二对可以追溯到::GetMessage(),但是我不知道是什么原因造成的要发送的消息。

0 个答案:

没有答案