Click here to Skip to main content
15,894,410 members
Articles / Desktop Programming / MFC

Repositioning Windows on Multiple Monitor Systems

Rate me:
Please Sign up or sign in to vote.
2.20/5 (6 votes)
6 Aug 2007CPOL2 min read 45.9K   1.7K   14  
How to reposition Windows on multiple monitor systems.
//Wrapping the API to some useful functions
#include "StdAfx.h"
#include ".\monitorinfo.h"
//for Multiple Monitors only inlcude once
//#ifndef COMPILE_MULTIMON_STUBS
	#define COMPILE_MULTIMON_STUBS
	#include <multimon.h>
//#endif

MonitorInfo::MonitorInfo() : m_Count(0), m_Primary(0)
{
	Update();
}

MonitorInfo::~MonitorInfo()
{
}
int MonitorInfo::GetNearestDisplay(CRect rc)
{
	HMONITOR hMonitor = MonitorFromRect( rc, MONITOR_DEFAULTTONEAREST ); ASSERT( hMonitor );

	MONITORINFO mi = {0};//MONITORINFOEX
	mi.cbSize = sizeof(MONITORINFO);

	BOOL b = GetMonitorInfo( hMonitor, &mi ) != 0; ASSERT( b );

	if( b )
	{
		for( int i = 0; i < m_Count; i++ )
		{
			if( m_Array[i] == mi.rcMonitor )
				return i;
		}	
	}
	return m_Primary;
}
int MonitorInfo::GetNearestDisplay(CPoint pt)
{
	HMONITOR hMonitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST ); ASSERT( hMonitor );

	MONITORINFO mi = {0};//MONITORINFOEX
	mi.cbSize = sizeof(MONITORINFO);

	BOOL b = GetMonitorInfo( hMonitor, &mi ) != 0; ASSERT( b );

	if( b )
	{
		for( int i = 0; i < m_Count; i++ )
		{
			if( m_Array[i] == mi.rcMonitor )
				return i;
		}	
	}
	return m_Primary;
}
//need to call once or by system settings changed
int MonitorInfo::Update()
{
	m_rcVirtualScreen = CRect( GetSystemMetrics( SM_YVIRTUALSCREEN ), GetSystemMetrics( SM_YVIRTUALSCREEN ), GetSystemMetrics( SM_CXVIRTUALSCREEN ), GetSystemMetrics( SM_CYVIRTUALSCREEN ) );
	m_Count = GetSystemMetrics( SM_CMONITORS );
	TRACE( "Virtual Screen: left = %ld, top = %ld, right = %ld, bottom = %ld\n", m_rcVirtualScreen.left, m_rcVirtualScreen.top, m_rcVirtualScreen.right, m_rcVirtualScreen.bottom );
	m_Array.RemoveAll();
	m_Primary = 0;
	m_csDevices.Empty();

	DISPLAY_DEVICE display;
	display.cb = sizeof( DISPLAY_DEVICE );
	DWORD dwNum = 0;
	//get names of all devices
	while( EnumDisplayDevices( NULL, dwNum, &display, 0 ) )
	{
		TRACE( "Device %s\n", display.DeviceString );
		m_csDevices += display.DeviceString;
		m_csDevices += "\n";

		dwNum++;
	}
	//enum all devices
	BOOL b = EnumDisplayMonitors(	0,				// handle to display DC 
									0,			    // clipping rectangle 
									MonitorEnumProc,// callback function
									(LPARAM) &m_Array // data for callback function 
								);
	
	m_Count = (int) m_Array.GetSize();
	//Check for primary
	for( int i = 0; i < m_Count; i++ )
	{
		CPoint pt = m_Array[i].CenterPoint();
		HMONITOR hMonitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST ); ASSERT( hMonitor );

		MONITORINFO mi = {0};//MONITORINFOEX
		mi.cbSize = sizeof(MONITORINFO);

		b = GetMonitorInfo( hMonitor, &mi ) != 0; ASSERT( b );

		if( mi.dwFlags & MONITORINFOF_PRIMARY )
		{
			m_Primary = i;
			break;
		}

	}
	return 0;
}
//Callback Function
BOOL MonitorInfo::MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData )
{
	TRACE( "MonitorEnumProc\n" );

	MonitorArray* pArray = (MonitorArray*) dwData;

	CRect rc = *lprcMonitor;

	pArray->Add( rc );

	return TRUE;
}
//iDisplay == -1 or not valid index => primary
int MonitorInfo::IsInDisplay(CRect rc, int iDisplay)
{
	if( iDisplay == -1 || m_Count <= iDisplay )
	{
		iDisplay = m_Primary;
	}

	CRect rcDisplay = m_Array[ iDisplay ];

	if( rcDisplay.PtInRect( rc.TopLeft() ) && rcDisplay.PtInRect( rc.BottomRight() ) )
	{
		return TRUE;
	}

	return FALSE;
}
CString MonitorInfo::GetName( int iDisplay )
{
	CString cs;
	AfxExtractSubString( cs, m_csDevices, iDisplay, '\n' );

	return cs;
}
//correct the RC for the display 
//return FALSE if movement is nessesary
int MonitorInfo::EnsureInMonitor(CRect& rc, int iDisplay)
{
	if( iDisplay == -1 || m_Count <= iDisplay )
	{
		iDisplay = m_Primary;
	}

	CRect rcDisplay = m_Array[ iDisplay ];

	BOOL bTL = rcDisplay.PtInRect( rc.TopLeft() );
	BOOL bBR = rcDisplay.PtInRect( rc.BottomRight() );

	if( bTL && bBR )
	{
		return TRUE;
	}
	//Not in Display

	int X = GetSystemMetrics( SM_CXDLGFRAME );
	int Y = GetSystemMetrics( SM_CXDLGFRAME );

	if( !bTL )
	{
		int dx = rc.left - rcDisplay.left;
		int dy = rc.top - rcDisplay.top;

		dx = min( 0, dx - X );
		dy = min( 0, dy - Y );

		rc.OffsetRect( -dx, -dy );
	}

	if( !bBR )
	{
		int dx = rc.right - rcDisplay.right;
		int dy = rc.bottom - rcDisplay.bottom;

		dx = max( 0, dx + X );
		dy = max( 0, dy + Y );

		rc.OffsetRect( -dx, -dy );
	}
	return FALSE;
}
int MonitorInfo::GetPrimary()
{
	return m_Primary;
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
I am living in germany and now living from programming for some Years. In my spare time I like sports as jogging, playing football (soccer) and basketball.

We must take care for our planet, because we and our family has no other. And everybody has to do something for it.

Comments and Discussions