VC 多屏控制显示文章整理

http://download.csdn.net/detail/finerpfw/9260539

一、多屏显示器的获取

1.      先将模板示例程序文件夹中的User32.Lib文件拷贝至程序文件夹中

2.      在用于检测显示器名称的.cpp中添加如下头文件

3.      添加检测显示器代码:

void CSHView::OnButton2()

{

// TODO: Add your control notification handlercode here

//获得显示屏的名称

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 ++;              

} while (flag);

}

通过调试时查看dd.DeviceName中的显示器名称。一般看到的显示器名称为

“\\.\DISPLAY1”第二个显示名称为“\\.\DISPLAY2”。

但对应到程序中设置的名称时String cstrDeviceName=“\\\\.\\DISPLAY1”。

VC程序中“\”需用“\\”表示。

4.      双屏显示代码

voidCSHView::OnButton1()

{

// TODO: Add your control notification handlercode here

 

CString cstrDeviceName="\\\\.\\DISPLAY2";  //显示器名称“\\\\.\\DISPLAY1”由OnButton2()中的DISPLAY_DEVICEdd得到,调试时查看dd.DeviceName的显示器名称

DEVMODE devMode;

devMode.dmSize = sizeof(DEVMODE);

devMode.dmDriverExtra = sizeof(DEVMODE);

int nRet = EnumDisplaySettings(cstrDeviceName,ENUM_CURRENT_SETTINGS,&devMode);

if(nRet)

{

           int x, y, cx, cy;

           x = devMode.dmPosition.x;

           y = devMode.dmPosition.y;

           cx = devMode.dmPelsWidth;

           cy = devMode.dmPelsHeight;

          

        g_pDlgShow=new CDialog1;

           g_pDlgShow->Create(IDD_DIALOG1);

           g_pDlgShow->ShowWindow(SW_SHOW);

           g_pDlgShow->SetWindowPos(&wndTop,x, y, cx, cy, SWP_SHOWWINDOW);

           g_pDlgShow->ShowWindow(SW_SHOWMAXIMIZED);

 }

 

}

5.      实际显示器号,跟电脑设置有关

如图:说明主显示屏的编号为:"\\\\.\\DISPLAY2"。

      副显示屏的编号为:"\\\\.\\DISPLAY1"。

 

本文下载 地址 :http://download.csdn.net/download/finerpfw/9260539

 

 

 

上面文章错误纠正:http://cauchy.blog.163.com/blog/static/175272539201251991510720/

二、VC多屏幕显示

       由于工程需要在多个显示器上显示不同类容,故查找了一些资料来满足这个功能。在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()中,这样程序一开始运行就可以在你想要显示的屏幕中运行.
 
 

三、其他封装多屏显示控制调用:

http://squallblog.blog.163.com/blog/static/1750938952012115112524980/
 

VC实现多屏显示(原创)

  直接贴源码吧,vc2008调试通过。只贴多屏显示相关操作类。

h文件如下:

/**********************************************

 Copyright(c) 欧博科技软件部

 文件名称:SquallMultiScreen.h
 文件描述:多屏显示操作类
 当前版本:1.0 v
 作    者:Squall(朱一)
 完成日期:2012-12-4

 说明:
 1、此类只适用于单卡双屏的控制(目前绝大多数A卡、N卡都是双屏显卡);
 2、双屏显卡包括一个主屏,一个副屏;可配置不同分辨率,可配置不同的位置关系;
 3、该类通过推算虚拟屏与主屏的位置关系,查找出副屏的坐标;

***********************************************/

#pragma once

class CSquallMultiScreen
{
private:
 CRect m_MainScreen;  //主屏
 CRect m_VirtualScreen; //虚拟屏(主屏和副屏的外接矩形)

public:
 CSquallMultiScreen(void);
 ~CSquallMultiScreen(void);

 longGetScreenCount();     //获取屏幕数量

 CRectGetVirtualScreenRect(void);  //返回虚拟屏尺寸
 CRect GetMainScreenRect(void);   //返回主屏尺寸
 CRect GetSecondaryScreenRect(void);  //返回副屏尺寸

 //显示窗体(将窗体移动至主屏或副屏的某个位置)
 void DisplayWindow( HWND hWnd, int x, int y, BOOL IsMainScreen = TRUE); 
};
 

cpp文件如下: 

#include"StdAfx.h"
#include "SquallMultiScreen.h"

CSquallMultiScreen::CSquallMultiScreen(void)
{
 m_MainScreen.left = 0;
 m_MainScreen.top = 0;
 m_MainScreen.right = ::GetSystemMetrics(SM_CXSCREEN);
 m_MainScreen.bottom = ::GetSystemMetrics(SM_CYSCREEN);

 m_VirtualScreen.left= ::GetSystemMetrics(SM_XVIRTUALSCREEN);
 m_VirtualScreen.top = ::GetSystemMetrics(SM_YVIRTUALSCREEN);
 m_VirtualScreen.right = m_VirtualScreen.left +::GetSystemMetrics(SM_CXVIRTUALSCREEN);
 m_VirtualScreen.bottom = m_VirtualScreen.top +::GetSystemMetrics(SM_CYVIRTUALSCREEN);
}

CSquallMultiScreen::~CSquallMultiScreen()
{
}

longCSquallMultiScreen::GetScreenCount()
{
 return ::GetSystemMetrics(SM_CMONITORS);
}

CRectCSquallMultiScreen::GetVirtualScreenRect(void)
{
 return m_VirtualScreen;
}

CRectCSquallMultiScreen::GetMainScreenRect(void)
{
 return m_MainScreen;
}

CRectCSquallMultiScreen::GetSecondaryScreenRect(void)
{
 if ( GetScreenCount() > 1 )
 {
  //用MainScreen和VirtualScreen的矩形中心点坐标来比较。判断8个方位的关系。

  CPoint mc =m_MainScreen.CenterPoint();  //MainCenter
  CPoint vc = m_VirtualScreen.CenterPoint(); //VirtualCenter
  CPoint TestPoint;

  ASSERT(!(vc.x == mc.x && vc.y == mc.y) );

  if ( vc.x ==mc.x && vc.y < mc.y ) //正上
  {
   TestPoint.SetPoint( vc.x, m_VirtualScreen.top );
  }

  if ( vc.x> mc.x && vc.y < mc.y ) //右上
  {
   TestPoint.SetPoint( m_VirtualScreen.right,m_VirtualScreen.top );
  }

  if ( vc.x> mc.x && vc.y == mc.y ) //正右
  {
   TestPoint.SetPoint( m_VirtualScreen.right, vc.y );
  }

  if ( vc.x> mc.x && vc.y > mc.y ) //右下
  {
   TestPoint.SetPoint( m_VirtualScreen.right,m_VirtualScreen.bottom );
  }

  if ( vc.x ==mc.x && vc.y > mc.y ) //正下
  {
   TestPoint.SetPoint( vc.x, m_VirtualScreen.bottom );
  }

  if ( vc.x< mc.x && vc.y > mc.y ) //左下
  {
   TestPoint.SetPoint( m_VirtualScreen.left,m_VirtualScreen.bottom );
  }

  if ( vc.x< mc.x && vc.y == mc.y ) //正左
  {
   TestPoint.SetPoint( m_VirtualScreen.left, vc.y );
  }

  if ( vc.x< mc.x && vc.y < mc.y ) //左上
  {
   TestPoint.SetPoint( m_VirtualScreen.left, m_VirtualScreen.top);
  }
  
  MONITORINFO mi;
  memset( &mi, 0, sizeof(MONITORINFO) );
  mi.cbSize = sizeof(MONITORINFO);

  HMONITORhScreen = MonitorFromPoint( TestPoint, MONITOR_DEFAULTTONEAREST );
  GetMonitorInfo( hScreen, &mi );
  ASSERT( mi.dwFlags == 0 );

  returnCRect( mi.rcMonitor );
 }
 else
 {
  return CRect(0,0,0,0);
 }
}

voidCSquallMultiScreen::DisplayWindow( HWND hWnd, int x, int y, BOOL IsMainScreen )
{
 ASSERT( hWnd );

 long nLeft =0,nTop = 0;

 if ( IsMainScreen)
 {
  nLeft = x;
  nTop = y;
 }
 else
 {
  if ( GetScreenCount() > 1 )
  {
   CRect SecRect = GetSecondaryScreenRect();

   nLeft= SecRect.left + x;
   nTop = SecRect.top + y;
  }
  else
  {
   nLeft = x;
   nTop = y;
  }
 }

 ::SetWindowPos(hWnd, NULL, nLeft, nTop, NULL, NULL, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER);
}

  以上是实现类。具体的使用非常简单,如果显示模态对话框,在对话框初始化函数中进行位置调整;如果显示非模态对话框,在Create函数后调整位置。
 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值