分享

Working with Multiple Monitors

 haodafeng_org 2011-05-19

Working with Multiple Monitors

Future releases of Windows 95, code named Memphis, and Windows NT support multiple display devices and monitors on a single system. The multiple monitor architecture (casually referred to as “MultiMon”) enables the operating system to use the display area from two or more display devices and monitors to create a single logical desktop. For example, in a MultiMon system with two monitors, the user could display applications on either monitor, or even drag windows from one monitor to another. DirectDraw supports this architecture, but there are a few nuances to be aware of, depending on the cooperative level your application uses.

A DirectDraw application should enumerate the devices, choose a device (or perhaps allow the user to choose the device to use), then create a DirectDraw object for that the device by using its hardware globally unique identifier (GUID). This technique will ensure the best performance on both MultiMon and single monitor systems and at all cooperative levels.

The currently active display device is referred to as the “default device,” or the “null device.” The latter name comes from the fact that the currently active display device is enumerated with NULL as its GUID. Many existing applications create a DirectDraw object for the null device, assuming that the device will be hardware accelerated. However, on multiple monitor systems, the null device isn’t always hardware accelerated; it depends on what cooperative level is set at the time.

In full-screen exclusive mode, the null device is hardware accelerated, but unaware of any other installed devices. This means that full-screen, exclusive mode applications will run as fast on a MultiMon system as any other system, but will not be able to use built-in support for spanning graphics operations across display devices. Full-screen, exclusive mode applications that need to use multiple devices can create a DirectDraw object for each device they want to use. Note that to create a DirectDraw object for a specific device, you must supply that device’s GUID (as it is enumerated when you call DirectDrawEnumerate).

When the normal cooperative level is set, the null device has no hardware acceleration; the null device is, effectively, an emulated logical device that combines the resources of two physical devices. Therefore, the null device has no hardware acceleration at all when the normal cooperative level is set. On the other hand, when the normal cooperative level is set, the null device is capable of automatically spanning graphics operations across monitors. As a result, negative coordinates for blit operations are valid when the logical location of secondary monitor is to the left of the primary monitor.

If your application requires hardware acceleration when the normal cooperative level is set, it must create a single DirectDraw object using a specific device’s GUID. Note that when you don’t use the null device, you don’t get automatic device spanning. That is, blit operations that cross an edge of the primary surface will be clipped (if you are using a clipper) or will fail, returning DDERR_INVALIDRECT.

As a rule on any system, you should set the cooperative level immediately after creating a DirectDraw object, before retrieving the object’s capabilities or querying for other interfaces. Additionally, avoid setting the cooperative level multiple times on a MultiMon system. If you need to switch from full-screen to normal mode, it is best to create a new DirectDraw object.
 
 
 
 
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.BOOL EnumDisplayMonitors(HDC hdc,LPCRECT lprcClip,MONITORENUMPROC lpfnEnum,LPARAM dwData)
  hdc是一个代表显示设备环境的句柄,lprcClip是指向一个矩形区域的指针。把这个矩形区域和设备环境中的可见区域取交集,得到的区域可能分布在多个显示器的显示区域中,EnumDisplayMonitors对每一个包含交集的显示区域调用一次MonitorEnumProc类型的函数。DwData为传递给MonitorEnumProc函数的数据。
  6.BOOL CALLBACK MonitorEnumProc(HMONITOR hmonitor,HDC hdcMonitor,LPRC lprcMonitor, DWORD dwData)
  MonitorEnumProc是一个被EnumDisplayMonitors函数调用的回调函数,它的内容可以由用户自定义。利用这两个函数,用户在进行跨多个显示器的显示时就可以利用每一个显示器的不同的显示特性。
  当然,并不是所有画图程序都必须调用这两个函数,这时你假设所有的显示器都使用同样颜色的分辨率。
  7.EnumDisplayDevices(LPVOID lpReserved,int iDeviceNum,DISPLAY_DEVICE×pDisplayDevice,DWORD dwFlags)
  EnumDisplayDevices列出系统中某个显示设备(以iDeviceNum为序号)的信息。与GetMonitorInfo相比,GetMonitorInfo对应的显示器必须是Windows虚拟桌面的一部分,而EnumDisplayDevices可以列出包括处于独立显示模式下的系统所安装的所有显示器的信息。它返回的信息储存在DISPLAY_DEVICE结构中,包括显示设备名称、对显示设备的描述和显示设备的状态。
  此外,一些原有的API调用如SystemParametersInfo和GetSystemMetrics也加入了对多显示器模式的支持。比如调用GetSystemMetrics时,如果用SM_XVIRTUALSCREEN、SM_YVIRTUALSCREEN、SM_CXVIRTUALSCREEN和SM_CYVIRTUALSCREEN,得到的是虚拟桌面左上角的坐标和整个的长度和宽度。
  我们在编程时特别要注意坐标的变化:首先单显示器下负坐标或大于SM_CXSCREEN和SM_CYSCREEN部分的窗口将被隐藏,而在多显示器模式下这些都是合法的。其次在确定应用程序窗口和对话框的位置时,要选择正确的显示器和正确的全局坐标(虚拟桌面坐标)。最后,在恢复原来存储的窗口之前,要检查一下这些窗口坐标的有效性。
#undef GetMonitorInfo
#undef GetSystemMetrics
#undef MonitorFromWindow
#undef MonitorFromRect
#undef MonitorFromPoint
#undef EnumDisplayMonitors
#undef EnumDisplayDevices

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多