直接贴源码吧,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文件如下:
cpp文件如下:/********************************************** 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); };
#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 ); }