【VS开发】MFC多显示器适配显示设置

时间:2024-03-04 11:15:21

由于工程需要在多个显示器上显示不同类容,故查找了一些资料来满足这个功能。在VC中分为三步来操作:检测显示器个数;读取屏幕分辨率和其他参数;设置程序的显示坐标。

第一步:检测屏幕个数

       网上查找到的通用方法有两个:EnumDisplayDevicess和GetSystemMetrics,下面分别介绍一下:

       A。EnumDisplayDevices(百度百科连接:http://baike.baidu.com/view/1080527.htm?fr=ala0_1,MSDN连接:http://msdn.microsoft.com/en-us/library/windows/desktop/dd162609(v=vs.85).aspx

函数功能:该函数可得到系统中显示设备的信息。   

函数原型:BOOL EnumDisplayDevices (PVOID Unused, DWORD iDevNum, PDISPLAY_DEVICE lpDisplayDevice, 

DWORD dwFlags);

其中第一个参数和最后一个参数现在都还没用到,主要是第二个参数和第三个,这里简要介绍一下

iDevNum:指定感兴趣的显示设备的索引值,操作系统通过索引值确定每一个显示设备。索引值是连续的整数。从0开始,例如:如果一个系统有三个显示设备,那么它们的索引值为0、1、2。

 lpdisplayDevice:DISPLAY_DEVICE结构的指针,该结构检索由iDevNum指定的显示设备的信息,在调用EnumDisplayDevices之前,必须以字节为单位把DISPLAY_DEVICE结构中cb元素初始化为DISPLAY_DEVICE结构的大小。

示例代码:

INT  iNumber=0;
 BOOL bFlag=TRUE;

 

DISPLAY_DEVICE dd;
 ZeroMemory(&dd, sizeof(dd));
 dd.cb = sizeof(dd);

 

 DEVMODE devMode;
 ZeroMemory(&devMode,sizeof(devMode));
 devMode.dmSize=sizeof(devMode);

 

 do
 {
   bFlag = EnumDisplayDevices(NULL, iNumber, &dd, 0);
  bFlag=bFlag&&EnumDisplaySettings(dd.DeviceName,ENUM_CURRENT_SETTINGS,&devMode);
   if (bFlag)
    iNumber += 1;
 } while (bFlag);

   其中iNumber中就为系统所带显示器的数量,网上很多地方都没有红色这一行,这样检测的结果并不准确,我用的笔记本不管是不是有外接显示器,检测出的数字始终为5,查看了这篇日志(http://hi.baidu.com/lin65505578/item/ffa9c32598b14fc3a5275add)后添加了红色语句后,运行结果就正常了。猜想EnumDisplayDevices只是检测系统中存在的显示设备,并不一定是当前一定在用的设备。添加设置语句后,就可以检测到正在使用的设备了。
B.int WINAPI GetSystemMetrics(  __in  int nIndex)
(MSDN连接:http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385(v=vs.85).aspx)
用于得到被定义的系统数据或者系统配置信息,百度百科上的资料较老,不全面。
只要设置nIndex为SM_CMONITORS即可,MSDN的解释为:The number of display monitors on a desktop. 
示例代码:

INT iNumber=GetSystemMetrics(SM_CMONITORS);
 CString csNum;
 csNum.Format(_T("%d"),iNumber);
 MessageBox(csNum,_T("显示器数量"),MB_OK);

相比A中的设置,这个简单多了,推荐使用此函数。

第二步,读取显示器参数及其他参数

该过程使用前面的两个API函数:EnumDisplayDevices和EnumDisplaySettings。

//初始化

BOOL bFlag;

DISPLAY_DEVICE dd;
 ZeroMemory(&dd, sizeof(dd));
 dd.cb = sizeof(dd);

 

 DEVMODE devMode;
 ZeroMemory(&devMode,sizeof(devMode));
 devMode.dmSize=sizeof(devMode);

bFlag=EnumDisplayDevices(BULL,iNumber,&dd,0);

if(bFlag)

return FLASE;

bFlag=EnumDisplayDevices(dd.DeviceName,ENUM_CURRENT_SETTINGS,&devMode);

iNumber为要查询的显示器编号,从0开始,主屏为0,然后1,2,3....一直下去。查询为EnumDisplaySettings(),查询的数据存储在devMode中,常用的为dmPosition(为当前显示器的坐标位置),dmPelsWidth,dmPelsHeight(为当前显示器的分辨率),其余根据自己需要参见MSDN(http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx).
第三步:设置当前程序的显示位置
在前两步的基础上,根据自己的需要来设置当前程序的显示坐标(ps:如果对系统虚拟坐标不了解的可以去查看一下相关资料)
示例代码:

CRect reTemp;
 reTemp.BottomRight()=CPoint(devMode.dmPelsWidth+devMode.dmPosition.x,devMode.dmPelsHeight);
 reTemp.TopLeft()=CPoint(devMode.dmPosition.x,devMode.dmPosition.y);
 MoveWindow(&reTemp);


这段代码添加在MFC程序中的OnInitDialog()中,这样程序一开始运行就可以在你想要显示的屏幕中运行.