直接貼源碼吧,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); };
#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 ); }