本文来自网易云社区

作者:梁敏

一、多屏设置

  1. 在设置-系统-可以点击显示器1和2,可以进行单独设置;

  2. “使之成为我的主显示器”可以设置当前显示器是主屏;主屏的选择会决定整个虚拟屏幕坐标起点的位置。

  3. 多显示器可以设置扩展,复制和独立展示。(独立显示是只在显示屏1 或者2上显示)

    • 扩展  - 设计,办公等场景。对于应用的意义则在于我们可以在两个或多个显示器上,分别打开不同的窗口,比如在一个显示器上显示网页,另一个显示器上进行文档编辑,在多任务应用时会非常方便。

    • 复制  - 会议、教学、商业展示。也就是说多屏显示系统中的每个显示设备,所显示的内容都是一样的,这一特点使它适合用在商务以及教学场合,比如大学课堂上讲课时或在会议上进行演示等。 - 设置完成后,和扩展模式中各显示器可以设置成各自的最佳分辨率不同,复制模式只能根据较低得分辨率进行设置,类似水桶效应:多屏显示系统中最小分辨率的设备决定整个画面的分辨率。所以在复制模式下,如果两款显示设备的分辨率不一样,则具有较高分辨率的显示设备,画面的质量必然受到影响,这也是复制模式的一个局限。

    • 独立。

  1. 设置是否在多显示器上显示任务栏,如图:                

  • 是否在所有显示器上显示任务栏

  • 所有任务栏

  • 主任务栏和打开了窗口的任务栏

  • 打开了窗口的任务栏

二、虚拟桌面坐标

  1. 主屏幕(Primary Screen)和扩展屏幕

    • 主显示屏的左上角决定了虚拟桌面的起始坐标(0,0)。其他显示器的显示区域的坐标由他和主显示屏的相对位置决定。

    • 扩展屏幕有多个。

  1. 虚拟屏幕(Virtual Screen)

    • 主屏和扩展屏组成的整个屏幕,就是虚拟屏幕。主屏和扩展屏,并非整齐排列,扩展屏可以放在主屏四周任何地方,但要相邻。

    • 虚拟桌面中的坐标是连续的,因此显示器2的坐标是主显示器1的显示区域的继续。例如如下显示器1分辨率1680x1050,显示器2分辨率1440x900,显示器2位于主显示器的正右方,则第二个显示区域的坐标是从(1680,0)到(3119,899)。                    

如果设置显示器2是主屏,显示器2的坐标是(0,0)->(1439,899),显示器1的坐标(-1679,1049)

三、系统相关API

Microsoft为支持多显示器模式提供了一些新的API调用,下面具体介绍它们的功能:

1.HMONITOR MonitorFromPoint(POINT pt,DWORD dwFlags)

MonitorFromPoint返回包含特定点(pt)的一个显示器句柄。如果pt不属于任何一个显示器,返回的显示器句柄由dwFlags标志决定:

MONITOR_DEFAULTTONULL时返回NULL;

MONITOR_DEFAULTTOPRIMARY时返回代表主显示器的HMONITOR句柄;

MONITOR_DEFAULTTONEAREST时返回最靠近pt点的显示器的HMONITOR句柄。

2.HMONITOR MonitorFromRect(LPCRECT lprc,DWORD dwFlags)

MonitorFromRect返回包含lprc代表的矩形的显示器句柄;如果包含此矩形的显示区域不止一个,则返回包含矩形最大部分的显示器句柄;如果矩形不属于任何一个显示区域,返回的句柄由dwFlags决定,规则与MonitorFromPoint相同。

3. HMONITOR MonitorFromWindow(HWND hwnd,DWORD dwFlags)

与MonitorFromRect类似,但输入是一个代表窗口的句柄hwnd而不是指向矩形的指针。

4.BOOL GetMonitorInfo(HMONITOR hMonitor,LPMONITORINFO lpmi)

GetMonitorInfo返回由hMonitor代表的显示器的有关信息,这些信息存储在指向MONITORINFO结构的指针——lpmi中。这些信息包括用RECT结构表示的显示器的显示区域的大小(如果这个显示器不是主显示器,RECT的坐标可能为负数),以及用RECT结构表示的显示器的工作区域的大小,工作区域是显示区域中除去系统任务栏和应用程序快捷方式栏所剩下的区域,还能够判断此显示器是否为主显示器,并返回一个标志。

5.GetSystemMetrics

获取坐标的时候用VIRTUALSCREEN参数

GetSystemMetrics(SM_CXVIRTUALSCREEN);//虚拟桌面宽度

GetSystemMetrics(SM_CYVIRTUALSCREEN);//虚拟桌面高度

GetSystemMetrics(SM_XVIRTUALSCREEN );//虚拟桌面左上角X坐标

GetSystemMetrics(SM_YVIRTUALSCREEN );//虚拟桌面左上角Y坐标

特别注意的是,多显示器的时候,SM_XVIRTUALSCREEN和SM_YVIRTUALSCREEN是可以为负值的。所以多显示器处理时,边界不要以为是(0,0)->(cx,cy)。多显示器的坐标是以主屏幕的左上角为(0,0)。
使用SM_CXSCREEN,SM_CYSCREEN获取只是主屏大小。

四、GUI扩展屏开发

GUI在多屏开发时主要问题是:当用户将主屏窗口移动到副屏后,需要记录窗口所处屏幕的信息。点击弹出菜单或者创建新窗口时,需要根据当前所处屏幕计算位置。

已经在我们代码里做了如下处理,开发时注意:

  1. 在用Window::CenterWindow显示新建窗口,如果希望窗口显示在和某窗口A在同一个显示器时,且窗口A不是新建窗口的父窗口,需要把该窗口A的句柄传入。例如我们的主窗口mainwnd,从主窗口新建窗口和主窗口在同一个显示器时,window->CenterWindow(mainwnd->GetHWND())。第二个参数wndCenter,代表是否要以指定窗口的居中显示。如果已经设置了父窗口,不需要这么设置,对于父窗口的。在CenterWindow在计算位置时会根据传入的窗口句柄所在显示器计算位置。SingletonShow这里也扩展了参数,可以传入窗口句柄。

void Window::CenterWindow(HWND hwndFrom, bool wndCenter/* = false*/)

eg:nim_ui::WindowsManager::SingletonShow<AboutForm>(AboutForm::kClassName, GetHWND());

  1. 在调用弹出的msgbox时,一定指定父窗口,这样弹出的msgbox就会和父窗口保持一致,不需其他处理。ShowMsgBox(m_hWnd, L"******", cb, L"", L"确定", L"");

  2. 在判断是否超出当前显示器边界的时候,这里要使用虚拟桌面的坐标来进行判断。

网易云大礼包:https://www.163yun.com/gift

本文来自网易云社区,经作者梁敏授权发

相关文章:
【推荐】 一个只有十行的精简MVVM框架

Windows扩展屏开发总结的更多相关文章

  1. Unity中调用Windows窗口句柄以及根据需求设置并且解决扩展屏窗体显示错乱/位置错误的Bug

    问题背景: 现在在搞PC端应用开发,我们开发中需要调用系统的窗口以及需要最大化最小化,缩放窗口拖拽窗口,以及设置窗口位置,去边框等功能 解决根据: 使用user32.dll解决 具体功能: Unity ...

  2. Windows统一平台: 开发小技巧

    Windows统一平台: 开发小技巧 技巧一: 在手机端拓展你应用的显示区域.(WP8.1中也适用) 对于Windows Phone系统的手机, 手机屏幕最上方为系统状态栏(System Tray), ...

  3. 【本人译作推荐】Windows 8应用开发:C#和XAML卷(原名:Building Windows 8 Apps with C# and XAML)

    [图书推荐] 译名:Windows 8应用开发:C#和XAML卷 原名:Building Windows 8 Apps with C# and XAML   编辑推荐 国内第一本使用XAML与C#语言 ...

  4. 《Windows IoT 应用开发指南》

    物物互联的时代已经到来,智能家居.智慧校园.智慧交通.可穿戴.无人机.全息投影,各种各样的新名词.黑科技层出不穷.当我们为五年前能够通过手机控制家电而欣喜若狂的时候,可曾憧憬过当前使用增强现实设备完成 ...

  5. Windows phone应用开发[17]-xap提交异常处理

    在windows phone 应用提交操作上早在2011年时就写过一篇Windows phone 应用开发[4]-应用发布,那时wp应用提交官方市场的流程繁杂[超过了5步].因为上传和填写应用信息页面 ...

  6. 一个仿windows泡泡屏保的实现

    一个仿windows泡泡屏保的实现 有天看到有人在百度知道上问windows 泡泡屏保该怎么用C#做,一时有趣,就做了一个出来,对于其中几个要点总结如下: 一,屏保程序的制作要求 屏保程序的扩展名是. ...

  7. WPF环境下多点触屏开发的一些经验(转)

    本系列将介绍Multi-Touch(MT)多点触控技术的相关内容,使开发人员了解如何在Windows 平台中开发出具有MT 功能的应用程序.众所周知Windows 7 操作系统自身已经支持具有MT 功 ...

  8. Windows搭建python开发环境,python入门到精通[一]

    从大学开始玩python到现在参加工作,已经有5年了,现在的公司是一家.net的公司用到python的比较少,最近公司有新项目需要用到python,领导希望我来跟其他同事training,就有了这篇博 ...

  9. 菜鸟学Windows Phone 8开发(2)——了解XAML

    本系列文章来源MSDN的 面向完全新手的 Windows Phone 8 开发 主要是想通过翻译本系列文章来巩固下基础知识顺带学习下英语和练习下自己的毅力 本文地址:http://channel9.m ...

随机推荐

  1. Android(java)学习笔记2:继承Thread类创建线程类

    1. 继承Thread类 创建线程类: package cn.itcast_02; /* * 该类要重写run()方法,为什么呢? * 不是类中的所有代码都需要被线程执行的. * 而这个时候,为了区分 ...

  2. 开源重磅,java内容管理系统CMS,点击就可以编辑,保存,轻松构建自己的站点

    买的暂时空间不给力.内存不足,老给关闭,先转到京东云上了,免费的,也不知免费多久. 这是地址2  http://java4cms.jd-app.com/index.html 这是地址  http:// ...

  3. 【LOJ6060】「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基)

    点此看题面 大致题意: 让你把\(n\)个数分成两部分,使得在两部分异或和之和最大的前提下,两个异或和中较小的那个尽量小.输出最优的较小异或和. 线性基 关于线性基,可以看一下这篇博客:线性基入门. ...

  4. IO缓冲区

    标准IO提供的三种类型的缓冲模式: (1)按块缓存:在填满缓冲区后才进行实际的设备读写操作 (2)按行缓存:指在接收到换行符('\n’)之前,数据都是先缓存在缓冲区的 (3)不缓存:允许你直接读写设备 ...

  5. TemplateSyntaxError at /article/list-article-titles/admin/

    如图红圈所示,发现一个注释掉的{% if userinfo %}标签竟然可以影响后面的标签快,不能注释,需要完全删除才不会报错. 继续这类django在html模板中直接注释掉发生错误以及解决方案: ...

  6. js 注册控件的onclick事件

    今天做了一个全选功能:1.点击全选,全部选中.选中状态再点击全选,全部取消选中2.点击成员,判断是否成员全部选中,true:全选为选中状态,false:全选为未选中状态. 使用js是比较麻烦的就是如何 ...

  7. jquery插件layer

    //信息框-例1 layer.alert('见到你真的很高兴', {icon: 6}); //信息框-例2 layer.confirm('你确定你很帅么?', {icon: 3}, function( ...

  8. Angularjs 数据过滤

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  9. o'Reill的SVG精髓(第二版)学习笔记——第四章

    第四章:基本形状 4.1线段 SVG可以使用<line>元素画出一条直线段.使用时只需要指定线段起止点的x和y坐标即可.指定坐标时可以不带单位,此时会使用用户坐标,也可以带上单位,如em. ...

  10. JS JavaScript事件循环机制

    区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...