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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章