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

 long GetScreenCount();     //获取屏幕数量

 CRect GetVirtualScreenRect(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() { }

long CSquallMultiScreen::GetScreenCount() {  return ::GetSystemMetrics(SM_CMONITORS); }

CRect CSquallMultiScreen::GetVirtualScreenRect(void) {  return m_VirtualScreen; }

CRect CSquallMultiScreen::GetMainScreenRect(void) {  return m_MainScreen; }

CRect CSquallMultiScreen::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);

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

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

void CSquallMultiScreen::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函数后调整位置。
 
 
2016-8-15 **********
  发现这篇日志点击量非常大,考虑了一下,为了让大家少走弯路,还是把最新的多屏显示类发给大家。新版使用vs2013编译通过。可适应任意多显卡、任意多屏幕。
h文件如下:
 
 
 
 

/********************************************** Copyright(c) 欧博科技软件部 文件名称:SquallMultiScreen.h 文件描述:多屏显示操作类 当前版本:2.0 v 作 者:Squall (朱一) 完成日期:2014-6-4 说明: 1、此类只适用于任意多屏幕的控制,无论你有几块显卡,接了几个屏幕。 2、每个屏幕可配置不同分辨率,可配置不同的位置关系; ***********************************************/ #pragma once #include <vector> class CSquallMultiScreen { private: int m_ScreenCount; //屏幕数量 CRect m_MainScreen; //主屏 CRect m_VirtualScreen; //虚拟屏(所有屏幕的外接矩形) std::vector<CRect> m_vecSecondaryScreen; //副屏(可以有多个) static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); public: CSquallMultiScreen(void); ~CSquallMultiScreen(void); void EnumMonitor(void); //枚举显示屏幕 int GetScreenCount(void); //获取屏幕数量 CRect GetVirtualScreenRect(void); //返回虚拟屏尺寸 CRect GetMainScreenRect(void); //返回主屏尺寸 //获取屏幕位置。索引:主屏0,第一副屏1,第二副屏2 ... CRect GetScreenRect(int nScreenIndex); //显示窗体在相应屏幕上。索引:主屏0,第一副屏1,第二副屏2 ... void DisplayWindow(HWND hWnd, int nScreenIndex, int x, int y); };

cpp文件如下:
 
 
 
 

#include "StdAfx.h" #include "SquallMultiScreen.h" #include <algorithm> CSquallMultiScreen::CSquallMultiScreen(void) { EnumMonitor(); } CSquallMultiScreen::~CSquallMultiScreen() { } void CSquallMultiScreen::EnumMonitor(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); m_ScreenCount = ::GetSystemMetrics(SM_CMONITORS); m_vecSecondaryScreen.empty(); HDC hdc = ::GetDC(NULL); EnumDisplayMonitors(hdc, NULL, CSquallMultiScreen::MonitorEnumProc, (LPARAM)this); ::ReleaseDC(NULL, hdc); //对多个副屏位置做排序 std::sort(m_vecSecondaryScreen.begin(), m_vecSecondaryScreen.end(), [](const CRect &rect1, const CRect &rect2){ if (rect1.left < rect2.left) return true; if (rect1.left == rect2.left && rect1.top <= rect2.top) return true; return false; }); } BOOL CSquallMultiScreen::MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData ) { CSquallMultiScreen *pThis = (CSquallMultiScreen *)dwData; //主要功能是检出副屏,主屏则忽略 if (!(lprcMonitor->left == 0 && lprcMonitor->top == 0)) { pThis->m_vecSecondaryScreen.push_back(*lprcMonitor); } return TRUE; }; int CSquallMultiScreen::GetScreenCount() { return m_ScreenCount; } CRect CSquallMultiScreen::GetVirtualScreenRect(void) { return m_VirtualScreen; } CRect CSquallMultiScreen::GetMainScreenRect(void) { return m_MainScreen; } CRect CSquallMultiScreen::GetScreenRect( int nScreenIndex ) { //当索引有错误,返回主屏 if (nScreenIndex >= m_ScreenCount || nScreenIndex == 0) return m_MainScreen; return m_vecSecondaryScreen[nScreenIndex - 1]; } void CSquallMultiScreen::DisplayWindow( HWND hWnd, int nScreenIndex, int x, int y ) { ASSERT( hWnd ); long nLeft = 0,nTop = 0; CRect ScreenRect = GetScreenRect(nScreenIndex); nLeft = ScreenRect.left + x; nTop = ScreenRect.top + y; ::SetWindowPos( hWnd, NULL, nLeft, nTop, NULL, NULL, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER ); }

猜你喜欢

转载自blog.csdn.net/dominating_/article/details/53259395