windows应用程序高分屏适配之坐标系--多屏场景

  windows系统下为了满足不同场景的应用,坐标系主要分为两类:逻辑坐标系和设备坐标系,一般而言GDI的文本和图形处理使用逻辑坐标系,而窗口以及鼠标的移动一般采用设备坐标系进行管理。

逻辑坐标系

  逻辑坐标系是面向GDI绘制是主要使用的对象DC(Device Context)应用,这种坐标系不考虑设备的具体类型,在绘制图形和文字时,windows会根据当前设置的映射模式将逻辑坐标自动转为设备坐标。

设备坐标系

  设备坐标是面向物理设备的坐标系,比如显示器,打印机等,这种坐标以像素或者设备所能表示的最小度量单位为基本单位。这种坐标系采用向下向右为正,横向为x轴方向,纵向为y轴方向,坐标原点根据
具体的设备链接和设置的不同存在一定差异。其中设备坐标系又可细分为屏幕坐标系、窗口坐标系和客户区坐标系三种相互独立的坐标系。三种坐标系示意图如下图所示。

window坐标系示意图

  • 1.屏幕坐标系

      屏幕坐标系是以主屏幕左上角为坐标原点,向右向下为正,见上图黑色字体。在多屏场景中,windows系统存在主副屏概念
    ,当前显示器的标识和是否为主屏可以通过[win7:桌面下鼠标右键->屏幕分辨率->设为主显示器]、[win10:设置->显示->设置为主显示器]进行主显示器设置,与此同时,当不清楚当前显示器具体位置时可以通过点击标识按钮,
    系统将会在每个显示器界面上标识出1,2,…的数字字样。同时可以通过拖动虚拟显示器位置改变显示器在屏幕坐标系的位置。
      当主屏在其他屏幕的左上侧时,此时屏幕上所显示的位置在屏幕坐标系的坐标均为正值,当一个显示器位于屏幕主显示器的左上角时,该显示器的点在坐标系中的位置存在负值。具体来说,当屏幕位于主显示器左侧时,
    x轴值为负值,当显示器位于主显示器上侧时,y轴坐标系为负值。一些与整个屏幕有关的函数均采用屏幕坐标系,如:GetCursorPos()、SetCursorPos()、CreateWindow()、MoveWindow()等。

  • 2.窗口坐标系

      窗口坐标系与屏幕坐标系相似,不同的是窗口坐标系是以当前窗口的左上角为坐标系的原点,向右向下为正。窗口包括标题栏、菜单栏、工具栏以及客户区等。坐标轴如上图所示。

  • 3.客户区坐标系

      在窗口的大部分区域也即是客户区,客户区坐标系比窗口坐标系更加细化,如上图所示。在该区域是窗口主要功能的展示区,其中包括客户区的绘图输出和窗口消息的处理等。

  本文主要记录在多屏场景中屏幕坐标系相关内容,尤其是高分屏场景的适配场景。

  在介绍高分屏适配之前需要了解2个概念,也即是DPI和DWM。其中DPI也即是(Dots Per Inch)每英寸像素点数量,在显示器上就是每英寸的像素个数,Window上一般默认是96 dpi 作为100% 的缩放比率,其他平台略有不同,例如mac端默认为72。
在windows系统中为了满足不同DPI屏幕显示自适应缩放,保证应用程序界面在不同的DPI显示器下正常显示,关于高DPI的支持, Windows XP时代就开始有了,
那时关于高DPI的支持比较简单,仅仅通过手动设置的方式进行文字或图片显示比例的调整,
但是从Vista/Win7 到现在Win8 /Win8.1, Windows关于高DPI的支持已经发生了很大的变化,也就是我们需要了解的另外一个概念DWM。

  DWM(Desktop Window Manager),该技术其实是用于实现当应用程序不能进行高DPI适应或者未禁止DWM虚拟化时,系统自动通过DWM进行调整,具体来说就是应用程序不需要自己实现不同分辨率显示器的文字或图片的缩放,只需要按照相同的处理逻辑按照100%显示比例进行应用程序界面的绘制,在最终显示之前系统会通过DWM自动将应用程序进行缩放,保证同样一个应用程序在1080p显示器上能看到正常的画面,但是在4K屏上就变的极其小的情况。
  对于win8.1以上系统DPI设置可以根据不同的需要设置当前应用程序是否开启DPI感知,以及开启DPI感知的具体级别。

typedef enum _Process_DPI_Awareness {
  Process_DPI_Unaware            = 0,
  Process_System_DPI_Aware       = 1,
  Process_Per_Monitor_DPI_Aware  = 2
} Process_DPI_Awareness;

  第一种Unaware, 该种方式是告诉系统, 我的程序不支持DPI aware, 请通过DWM虚拟化帮我们实现。 该方式通过GetWindowRect取到的坐标都是经过DWM缩放后的, 无论对方窗口是不是支持DWM虚拟化。

  第二种方式是System DPI aware, 该方式下告诉系统, 我的程序会在启动的显示器上自己支持DPI aware, 所以不需要对我进行DWM 虚拟化。 但是当我的程序被拖动到其他DPI不一样的显示器时, 请对我们先进行system DWM虚拟化缩放。

  第三种方式是Per Monitor DPI aware, 该方式是告诉系统, 请永远不要对我进行DWM虚拟化,我会自己针对不同的Monitor的DPi缩放比率进行缩放。 这种方式需要自己完成对高DPI的支持。
chrome 是设置的Per Monitor DPI aware 猜测其UI应该自己内部实现了对高DPI的支持,基于CEF的开发 建议设置System DPI aware 来完成对高DPI的支持。

  在windows8.1以上系统可以通过以下API获取或设置系统DPI相关的信息:

GetDpiForMonitor	    # Queries the DPI information associated with a monitor.
GetDpiForSystem	        # Returns the system DPI.
GetDpiForWindow	        # Returns the current DPI for the specified window.
GetProcessDpiAwareness	# Retrieves the DPI virtualization mode of the specified process.
GetSystemMetricsForDpi	# A variant of GetSystemMetrics that returns values scaled to a specific DPI.
SetProcessDpiAwareness	# Sets the DPI virtualization mode for the current process.
GetSystemDpiForProcess	# Retrieves the system DPI associated with a given process.

更多详细的函数信息,可以参阅这个链接:https://docs.microsoft.com/zh-cn/windows/win32/hidpi/high-dpi-reference

就先记录到这里吧,下篇我们将整理一下windows高DPI下鼠标坐标相关问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值