如何在DPI识别的获胜应用程序上缩放标题栏?

Dea*_*ane 18 c++ winapi dpi windows-8.1 windows-10

我通过设置<dpiAware>True/PM</dpiAware>清单文件使每个监视器的应用程序dpi感知.我可以使用进程资源管理器验证这确实有效,或者通过调用GetProcessDpiAwareness来验证.

这一切都运行正常,我可以在我的代码中很好地扩展客户端区域中的任何内容.但是,我唯一的问题是,如果我将我的应用程序从system-dpi监视器拖到非系统dpi监视器,标题栏和任何系统菜单将变得太大或太小.对于大多数内置应用程序(例如计算,边缘浏览器等),情况并非如此,因此必须妥善扩展它.MS的开发人员有没有这样做过?

下面的截图应该更好地解释我的问题.另请注意,关闭,最小和最大按钮之间的填充在缩放(96dpi)时是不同的.

截图

示例应用程序我附加了一个非常简单的应用程序,每个监视器dpi意识到.

jos*_*736 10

Windows 10周年更新(v1607)添加了一个新的API,您必须调用该API才能启用非客户区域的DPI扩展:EnableNonClientDpiScaling.WM_NCCREATE收到此函数时,应调用此函数.在窗口创建期间,消息将发送到窗口的过程回调.

例:

case WM_NCCREATE:
{
    if (!EnableNonClientDpiScaling(hWnd))
    {
        // Error handling
        return FALSE;
    }

    return DefWindowProcW(...);
}
Run Code Online (Sandbox Code Playgroud)

如果应用程序的DPI感知上下文是DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,EnableNonClientDpiScaling则应省略调用,因为它不会产生任何影响,尽管该函数仍将成功返回.

文档:

默认情况下,不启用顶级窗口的非客户端扩展.您必须调用此API,以便为您希望自动为非客户区域扩展的每个顶级窗口启用它.一旦你这样做,就无法禁用它.启用非客户端扩展意味着系统为窗口绘制的所有区域将自动缩放以响应窗口上的DPI更改.其中包括标题栏,滚动条和菜单栏等区域.如果希望EnableNonClientDpiScaling操作系统负责根据监视器的API自动以正确的大小呈现这些区域,则需要调用.

有关Windows 10 AU中DPI扩展更改的其他信息,请参阅此博客文章.


小智 7

MS的开发人员有没有这样做过?

这有一个非常令人失望的答案.使用Alin Constantin的WinCheat并检查Calculator的顶级窗口,我看到窗口大小为320x576,客户端大小也是320x576.

换句话说,Microsoft通过抑制窗口的非客户区域完全避免了这个问题,而是将所有内容放在客户区域中.为您做好这项工作可能涉及自定义绘制标题栏.

值得注意的是,计算器和例如Windows资源管理器不会对标题栏使用相同的颜色.做标题栏自定义绘图的计算器可以很好地解释这一点.

  • 试图决定我是应该给这个问题赏金还是写一个我自己的新问题.hvd,我喜欢你的答案,我认为这是正确的,但它还远远不够.正如其他评论中所指出的那样(特别参见上文),沼泽标准的Win32 Run对话框正确.据我所知,使用Spy ++,它不是*所有者 - 绘制其非客户区域,我非常怀疑shell团队已经将"运行"启动的"浏览"对话框子类化为owner-draw*其*标题栏.所以*必须*是一种合理的方式.他们不可能是完全白痴. (2认同)