Windows下的双显的设置

XP系统下设置双显的过程

电脑:AUSUS K50I

显卡为NVIDIA N1-0P-GE

在桌面上右击,选属性。在弹出窗口中找到设置选项卡,会看到有两个显示器编号。点选2号显示器。在下面找到两个选项,先选择下面的扩展桌面到此监视器,然后再选上面的设置此显示器为主显示器。点下面的应用按钮,然后选1号显示器,把下面两个选项中的扩展桌面到此监视器这个选项取消选择,就可以了。

 


 

 

2、一些应用程序在双显时的特性

(1)      PPT

把PPT拖到副显,此时按F5放映PPT。却是在主显示PPT全屏放映,而副显还是显示编辑状态的PPT。

(2)      RDP

RDP7不支持双显。Win7 下的RDP才支持双显。

(3)      按Ptr Sc键,把桌面的屏幕保存到mspaint中,此时看到是两个屏幕的和。

长*宽是否2646*768 ,这个大小就是双显的大小

可以看到2646是主显的分辩率的宽+副显的分辨率的宽。(1280+1366)


Introduction

This has been an ongoing topic for a while and I keep on getting question(s) on how can we launch Windows or in our case application(s) in different screens. In the place that I currently work, City of Dreams, we have many different types of adapters for many A/V systems and the applications like Lucky Draw, Slot Results, etc. have to be automatically launched on the correct AV to have effects like Animation(s) on one type, random numbers on other, etc.

Launcher


Launched

 

The AllScreens

This is all it takes to get the information of all the screens currently hosted in the systemSystem.Windows.Forms.Screen.

So to populate our dropdown; loop through the:

Screen[] scr = Screen.AllScreens
this.cmbDevices.Items.Clear();
foreach (System.Windows.Forms.Screen s in scr)
{
    strDeviceName = s.DeviceName.Replace("\\\\.\\", "");
    this.cmbDevices.Items.Add(strDeviceName);
    // you can check the device is primary or not this way
    if (s.Primary) this.cmbDevices.Items.Add(">" + strDeviceName);
    else this.cmbDevices.Items.Add(strDeviceName);
}
this.cmbDevices.SelectedIndex = 0;

Launch

There are only two properties that have to be set correctly in order to ensure it is properly launched into the correct display. Form.StartPosition & Form.Location.

Screen[] scr = Screen.AllScreens
Form oForm = new Form()
oForm.Left = scr[0].Bounds.Width;
oForm.Top = scr[0].Bounds.Height;
oForm.StartPosition = FormStartPosition.Manual;
oForm.Location = scr[0].Bounds.Location;
        oForm.Show();


Putting It All Together

Here we go, this is all it takes to launch your forms into user selected display.

public partial class frmMain : Form
{
    Form[] aryForms = new Form[5];                      // Allow 5 total forms.
    int currentPointer = 0;                             //
    Screen[] scr = Screen.AllScreens;
    
    public frmMain()
    {
        InitializeComponent();
        LoadScreen();
    }
    
    private void LoadScreen()
    {
        String strDeviceName = String.Empty;
        
        this.cmbDevices.Items.Clear();
        foreach (Screen s in scr)
        {
            strDeviceName = s.DeviceName.Replace("\\\\.\\", "");
            this.cmbDevices.Items.Add(strDeviceName);
            /* Enable this section, if you want to point to 
	   user this is the default screen.
            if (s.Primary) this.cmbDevices.Items.Add(">" + strDeviceName);
            else this.cmbDevices.Items.Add(strDeviceName);
            */
        }
        this.cmbDevices.SelectedIndex = 0;
    }
    
    private void btnLaunchIn_Click(object sender, EventArgs e)
    {
        int intLaunchScreen = getScreenNumber(this.cmbDevices.SelectedItem.ToString());
        
        if (currentPointer <= 4)
        {
            aryForms[currentPointer] = new frmLaunchedWindow();
            aryForms[currentPointer].Text = 
		aryForms[currentPointer].Text + currentPointer;
            aryForms[currentPointer].Left = scr[intLaunchScreen].Bounds.Width;
            aryForms[currentPointer].Top = scr[intLaunchScreen].Bounds.Height;
            aryForms[currentPointer].StartPosition = FormStartPosition.Manual;
            aryForms[currentPointer].Location = scr[intLaunchScreen].Bounds.Location;
            //Point p = new Point(scr[0].Bounds.Location.X, scr[0].Bounds.Location.Y);
            //aryForms[currentPointer].Location = p;
            aryForms[currentPointer].Show();
            currentPointer += 1;
        }
    }
    private int getScreenNumber(String DeviceID)
    {
        int i = 0;
        foreach (Screen s in scr)
        {
            if (s.DeviceName == "\\\\.\\"+DeviceID) return i;
            i += 1;
        }
        // if cannot find the device reset to the default 0
        return 0;
    }
}


 二、Windows下的多显介绍

 

 

Positioning Objects on a Multiple Display Setup

 The following sample code demonstrates how applications can correctly position objects on multiple displays. Note, do not assume that the RECT is based on the origin (0,0).

#include <windows.h>
#include "multimon.h"    

#define MONITOR_CENTER     0x0001        // center rect to monitor 
#define MONITOR_CLIP     0x0000        // clip rect to monitor 
#define MONITOR_WORKAREA 0x0002        // use monitor work area 
#define MONITOR_AREA     0x0000        // use monitor entire area 

// 
//  ClipOrCenterRectToMonitor 
// 
//  The most common problem apps have when running on a 
//  multimonitor system is that they "clip" or "pin" windows 
//  based on the SM_CXSCREEN and SM_CYSCREEN system metrics. 
//  Because of app compatibility reasons these system metrics 
//  return the size of the primary monitor. 
// 
//  This shows how you use the multi-monitor functions 
//  to do the same thing. 
// 
void ClipOrCenterRectToMonitor(LPRECT prc, UINT flags)
{
    HMONITOR hMonitor;
    MONITORINFO mi;
    RECT        rc;
    int         w = prc->right  - prc->left;
    int         h = prc->bottom - prc->top;

    // 
    // get the nearest monitor to the passed rect. 
    // 
    hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);

    // 
    // get the work area or entire monitor rect. 
    // 
    mi.cbSize = sizeof(mi);
    GetMonitorInfo(hMonitor, &mi);

    if (flags & MONITOR_WORKAREA)
        rc = mi.rcWork;
    else
        rc = mi.rcMonitor;

    // 
    // center or clip the passed rect to the monitor rect 
    // 
    if (flags & MONITOR_CENTER)
    {
        prc->left   = rc.left + (rc.right  - rc.left - w) / 2;
        prc->top    = rc.top  + (rc.bottom - rc.top  - h) / 2;
        prc->right  = prc->left + w;
        prc->bottom = prc->top  + h;
    }
    else
    {
        prc->left   = max(rc.left, min(rc.right-w,  prc->left));
        prc->top    = max(rc.top,  min(rc.bottom-h, prc->top));
        prc->right  = prc->left + w;
        prc->bottom = prc->top  + h;
    }
}

void ClipOrCenterWindowToMonitor(HWND hwnd, UINT flags)
{
    RECT rc;
    GetWindowRect(hwnd, &rc);
    ClipOrCenterRectToMonitor(&rc, flags);
    SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}



三、RepositioningWindows on Multiple Monitor Systems

 参考代码:

http://download.csdn.net/detail/chenyujing1234/5218722

Introduction

On systems with more than one display, you can get into trouble because of compatibility issues for functions like:

SystemParametersInfo( SPI_GETWORKAREA, 0, &rc, 0 );//only primary Monitor

Here is a possible setup for two displays: the left (1) is the standard monitor, and the right (2) is the extension monitor, for instance, for less needed information like help, e-mail, or browsing.


Background

Last week, I got a problem of restoring a windowon a computer which had multiple monitors. I looked for some samples, but found no good ones, so I wrote some code to solve the issue. And, I want to demonstrate my new knowledge and publish it here.

But there are other setups possible; it might look strange, for instance, to have the right monitor as the primary one.This means that the coordinates of the left monitor have negative values.



The taskbar

The taskbar also needs some space, so it is better that this area wont be used to show windows. The taskbar can have different positions. This is illustrated from the standard position (1) up to three different positions (2)-(4).



Using the code

I packed all the interesting code in a designed class to concentrate(浓缩)it and for ease of use. Because of

#define COMPILE_MULTIMON_STUBS, you got to pay some attention on how to use the class. If you find a better way, let me know it.

Now I have coded a global object, so you don't need an extra object, and the object is available if you include the files in your project.

//Fetch informations
int cnt ) gMonitor.GetCount(); 
int iMonitor = gMonitor.GetPrimary();

//test for repositioning
CRect rc;
GetWindowRect( rc );

iMonitor = gMonitor.GetNearestDisplay( rc ); //also overloaded for point

if( !gMonitor.EnsureInMonitor( rc, iMonitor ) )
    MoveWindow( rc );

Points of interest

This code can help you for a better user experience with multiple monitor systems, because a window will be moved if it doesn't fit on one physical screen.

It gets real tricky. When the primary display is the right one (or the upper?), then the left (top) has negative values and sizing needs some extra lines of code.

Also, watch out for the taskbar area, which is another pitfall.


 

 

 

 

 

API

Windows系统的多显示器模式的编程 

 这几天研究了一下Windows系统的多显示器模式的编程,实现了Windows下 支持10显示器模式的通用com组件,这里做一个整理和回顾,希望能对再这方面开发的兄弟们有些启发和帮助: 
 (一) Windows系统下的多显示器模式的原理     
 Microsoft新的操作系统(Windows 98\Windows 2000\Windows XP)内置了对多监视器的支持,即用户可以在一台计算机上安装多个显示卡并接上多个显示器,然后把这些显示器的显示区域组织成一个 大的虚拟的Windows桌面。每一个显示区域的底部都有系统任务栏,我们 可以在任何一个显示区域内增加桌面快捷方式,这样就可以在第一个显示区域上用Visual C++编程,同时在第二个显示区域上打开Internet Explorer上网——再也不用进行麻烦的切换了。     
多显示器模式的原理实际上很简单,主要还是要靠操作系统的支持,比如 WinXP就支持10个显示器,本文所使用的调试和开发环境都是以WinXP为主,其余的原理都相同慢慢调试就行了. 
Windows提供的多显示器模式主要有以下三个功能:    
1.更大的Windows桌面:在多显示器模式下,可以把多个显示器的显示区域结合在一起来显示Windows桌面,不管这些显示器的尺寸、物理位置、分辨率和刷新频率是否相同。当我们运行一个应用程序时,程序的主窗口可以位于任何一个显示器的显示区域内,也可以跨多个显示区域。我们也可以把一个程序的窗口从一个显示区域移到另一个显示区域中。  
2. 屏幕复制或远程显示:我们可以让两个显示器显示相同的内容。在进行培训或者向众人进行演示时,这个特点是很有用的。利用这个特性,技术支持人员还可以对应用程序进行远程监视和调试。   
3.多重独立显示:在以上的两种模式下,所有的显示区域都是Windows虚拟桌面的一部分,但是在 多重独立显示模式下,应用程序访问的显示器并不属于Windows虚拟桌面。假设系统的第二个显示器是一个高分辨率的大尺寸显示器,我们可以把它用做CAD应用程序的专用显示。通过 在CAD应用程序中调用新的Windows API,我们可以借助GDI在上面画图。独立显示器的显示区域没有桌面上的任何对象(任务栏和快捷方式),它与Windows桌面是独立的。这可以避免Windows桌面对应用程序输出的任何干扰,我们也 不用担心会在无意中把其它的窗口拽到独立显示的显示区域中,这种方式就好像为应用程序提供了一个专用的显示器。
 (二)理解虚拟桌面(Virtual Desktop)及其坐标 既然是要对多显示器模式进行编程和开发,那么我们就要首先理解Windows的虚拟桌面(Virtual Desktop))及其坐标了.这是我们编程开发的基础,理解了一切就很顺利了,几乎没有什么难度.   在单显示器系统中,实际Windows桌面的形状和大小与显示器是相同的。在多显示器模式下,每一个显示器

实际上是一个大虚拟桌面的一个“子视窗”。   我们可以通过控制面板中的显示器属性对每一个显示器的显示区域的大小(分辨率)和相对位置进行调整,所有这些显示区域互相连接但并不重叠。
图一中的显示器1是主显示器, 主显示器的作用是确定虚拟桌面的坐标。不管主显示器的位置如何,它的显示区域的左上角的坐标定为虚拟坐标的零点(0,0),右下角的坐标是(X-1,Y-1)(假设主显示器的分辨率为X×Y), 其余显示区域的坐标由它和主显示器的相对位置决定。通常虚拟桌面中显示区域的相对位置和实际显示器的物理相对位置是相同的。因为所有显示区域必须相连,因此可以用一个包含所有显示区域的最小矩形来表示虚拟桌面的大小。图一中的矩形边界代表了虚拟桌面的范围。     
因为虚拟桌面中的坐标系统必须是连续的,因此第二个显示区域的坐标是主显示器的显示区域的继续。假设两个显示器都使用1024×768的分辨率,并且第二个显示器位于第一个显示器(主显示器)的正右方,则 第二个显示区域的坐标是从(1024,0)到(2047,767)。   但是并不是所有的显示区域都具有相同的分辨率,而且这些显示区域也不一定是底边对齐的。就像图一中显示的那样,你真正能看到的有效显示区域是红色+兰色+紫色的不规则区域,而黄色区域虽然也属于虚拟桌面的一部分,但它不属于任何一个显示区域,这部分也叫做 无效区域
如图一中所示,假设显示器1的分辨率是1024×768,显示器2的分辨率为800×600,显示器3的分辨率为640×480。零点的位置如图中所示,显示器1的坐标为(0,0)到(1023,767), 显示器2的坐标为(-800,168)到(-1,767),显示器3的坐标是(1024,0)到(1663,479)。而(-800,0)到(-1,167)以及(1024,480)到(1663,767)这两块无效区域是不能显示任何信息的,系统不会允许用户把鼠标移动到这两个区域。需要注意的是无效区域是包括在虚拟桌面中的,因此图一中的虚拟桌面的大小是从(-800,0)到(1663,767)。

我在编程开发的过程中就使用了2个显示器,一个是自己的笔记本,分辨率为1024×768作为主显示器,另外一个由于比较懒,直接找了一个小巧的NEC12寸屏幕的小黑白显示器,不是为了别的搬着方便啊,这个NEC黑白支持分辨率800×600,强吧. 如下图我是直接设置了扩展桌面,两个显示器就都可以使用了 在这里要注意主显示器和副显示器的区别,其实主显示器和副显示器你是可以进行任意调整的.
(三)系统支持编程开发的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.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是一个被函数调用的回调函数,它的内容可以由用户自定义。利用这两个函数,用户在进行跨多个显示器的显示时就可以利用每一个显示器的不同的显示特性。   当然,并不是所有画图程序都必须调用这两个函数,这时你假设所有的显示器都使用同样颜色的分辨率。 

 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部分的窗口将被隐藏,而在多显示器模式下这些都是合法的
其次在确定应用程序窗口和对话框的位置时,要 选择正确的显示器和正确的全局坐标(虚拟桌面坐标)。最后,在恢复原来存储的窗口之前,要检查一下这些窗口坐标的有效性。      
这些都可以在微软的MSDN上去查出来,需要仔细的看一看,每个API都亲自试一试.      大家可以参考MSND的一篇文章"How to Exploit Multiple Monitor Support in Memphis and Windows NT 5.0",说的很详细

 

(四)实现多屏幕编程的组件设计 这个组件参考了网上的许多资料,这里先向那些无私的同行表示感谢,我做的工作只是将他们的成果进行了系统化的整理...... 

组件的设计流程如下: 

(1).初始化程序 Syntax:: MScreenInfo(); 

Description : 部件构造函数,初始化部件,获取系统屏幕信息,设置部件属性。

 (2). 获取指定屏幕的宽度 

Syntax: Short GetScreenWidth( Short ScreenNo) ; 

Input : ScreenNo -- 指定屏幕的序号,0 -- m_monitorNum-1; Return: Screen Width in Pixel;

 Decription: 获取ScreenNo指定屏幕的宽度。

 (3). 获取指定屏幕的高度

 Syntax: Short GetScreenHeight( Short ScreenNo) ; 

Input : ScreenNo -- 指定屏幕的序号,0 -- m_monitorNum-1; Return: Screen Height in Pixel; 

Decription: 获取ScreenNo指定屏幕的高度。 程序流程图:

与图2相同,只是最后一步返回dm.dmPelsHeight.

 (4). 获取指定屏幕的坐标原点-left Syntax: Short GetScreenLeft( Short ScreenNo) ;

 Input : ScreenNo -- 指定屏幕的序号,0 -- m_monitorNum-1; Return: Screen Left in Pixel;

 Decription: 获取ScreenNo指定屏幕的坐标原点-left。 程序流程图:与图2相同,只是最后一步返回dm.dmPosition.x.

(5). 获取指定屏幕的坐标原点-top Syntax: Short GetScreenLeft( Short ScreenNo) ; 

Input : ScreenNo -- 指定屏幕的序号,0 -- m_monitorNum-1; Return: Screen Top in Pixel; 

Decription: 获取ScreenNo指定屏幕的坐标原点-top。 程序流程图:与图2相同,只是最后一步返回dm.dmPosition.y.


(6). 获取主屏幕--Primary Screen

 Syntax: Short GetPrimaryScreen();

 Input: Null; 

Return: Primary Screen No, 0 -- m_monitorNum - 1

 Description: 获取主屏幕的序号。 程序流程:依次判断那一个屏幕的原点是(0, 0). 

(五)组件开发的实现和主要代码

 1 开发环境 操作系统: WindowsXP  

  编程环境: VC 6.0 

2 组件接口如下

 3 主要代码 


// 获得显示器的数量
 CMScreenInfoCtrl::CMScreenInfoCtrl()
 {
	InitializeIIDs(&IID_DMScreenInfo, &IID_DMScreenInfoEvents); 
	// 找出显示器的总数量 
	int   i; 
	BOOL flag; 
	DISPLAY_DEVICE dd;
	i = 0; 
	flag = true;    
	ZeroMemory(&dd, sizeof(dd));      
	dd.cb = sizeof(dd); 
	do 
	{    
		flag = EnumDisplayDevices(NULL, i, &dd, 0);    
		if (flag) 
			i += 1; 
	} while (flag); 
	m_monitorNum = i;  
 // 总数量
 }

 // 获得显示区宽度
short CMScreenInfoCtrl::GetScreenWidth(short ScreenNo)
{
	if (ScreenNo < 0 || ScreenNo >= m_monitorNum)
		return 0; 
	BOOL flag; 
	DISPLAY_DEVICE dd;      
	ZeroMemory(&dd, sizeof(dd));      
	dd.cb = sizeof(dd); 
	flag = EnumDisplayDevices(NULL, ScreenNo, &dd, 0); 
	if (!flag) 
		return 0; 
	DEVMODE dm; 
	ZeroMemory(&dm, sizeof(dm)); 
	dm.dmSize = sizeof(dm); 
	flag = EnumDisplaySettings((char*)dd.DeviceName,ENUM_CURRENT_SETTINGS, &dm); 
	if (!flag) 
		return 0; 
	return (short) dm.dmPelsWidth; 
} 

// 设置显示区宽度 
void CMScreenInfoCtrl::SetScreenWidth(short ScreenNo, short nNewValue) 
{ 
	SetModifiedFlag(); 
}
// 获得显示区宽度 
short CMScreenInfoCtrl::GetScreenHeight(short ScreenNo)
{ 
	if (ScreenNo < 0 || ScreenNo >= m_monitorNum) 
		return 0; 
	BOOL flag; 
	DISPLAY_DEVICE dd;      
	ZeroMemory(&dd, sizeof(dd));      
	dd.cb = sizeof(dd); 
	flag = EnumDisplayDevices(NULL, ScreenNo, &dd, 0); 
	if (!flag) 
		return 0;
	DEVMODE dm; 
	ZeroMemory(&dm, sizeof(dm)); 
	dm.dmSize = sizeof(dm); 
	flag = EnumDisplaySettings((char*)dd.DeviceName,ENUM_CURRENT_SETTINGS, &dm); 
	if (!flag) 
		return 0; 
	return (short) dm.dmPelsHeight; 
}

// 设置显示区高度 
void CMScreenInfoCtrl::SetScreenHeight(short ScreenNo, short nNewValue)
{
	SetModifiedFlag(); 
}
// 获得显示区Y坐标 
short CMScreenInfoCtrl::GetScreenTop(short ScreenNo) 
{ 
	if (ScreenNo < 0 || ScreenNo >= m_monitorNum) 
		return -1; BOOL flag; DISPLAY_DEVICE dd;      
	ZeroMemory(&dd, sizeof(dd));     
	dd.cb = sizeof(dd); 
	flag = EnumDisplayDevices(NULL, ScreenNo, &dd, 0); 
	if (!flag) 
		return -1; 
	DEVMODE dm; 
	ZeroMemory(&dm, sizeof(dm)); 
	dm.dmSize = sizeof(dm); 
	flag = EnumDisplaySettings((char*)dd.DeviceName,ENUM_CURRENT_SETTINGS, &dm); 
	if (!flag) 
		return -1; 
	return (short) dm.dmPosition.y ;
}

// 设置显示区Y坐标 
void CMScreenInfoCtrl::SetScreenTop(short ScreenNo, short nNewValue) 
{ 
	SetModifiedFlag(); 
} 
// 获得显示区X坐标 
short CMScreenInfoCtrl::GetScreenLeft(short ScreenNo)
{ 
	if (ScreenNo < 0 || ScreenNo >= m_monitorNum) 
		return -1; 
	BOOL flag; 
	DISPLAY_DEVICE dd;      
	ZeroMemory(&dd, sizeof(dd));      
	dd.cb = sizeof(dd); 
	flag = EnumDisplayDevices(NULL, ScreenNo, &dd, 0); 
	if (!flag) 
		return -1; 
	DEVMODE dm; 
	ZeroMemory(&dm, sizeof(dm)); 
	dm.dmSize = sizeof(dm); 
	flag = EnumDisplaySettings((char*)dd.DeviceName,ENUM_CURRENT_SETTINGS, &dm); 
	if (!flag) 
		return -1; 
	return (short) 
	dm.dmPosition.x ; 
} 
// 设置显示区X坐标 
void CMScreenInfoCtrl::SetScreenLeft(short ScreenNo, short nNewValue)
{ 
	SetModifiedFlag(); 
} 

// 获得主显示区 
short CMScreenInfoCtrl::GetPrimaryScreen() 
{ 
	// TODO: Add your property handler here 
	if (m_monitorNum <= 1) 
		return 0; 
	// if the Screen Top = 0 and Left = 0, then, it’s the Primary Screen 
	short i; 
	for (i=0; i<m_monitorNum; i++)
	{    
		if (GetScreenTop(i)==0 && GetScreenLeft(i)==0) 
			return i; 
	} 
	return 0; 
} 
// 设置主显示区 
void CMScreenInfoCtrl::SetPrimaryScreen(short nNewValue)
{ 
	SetModifiedFlag();
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值