www.pudn.com > multiMonitor_demo.rar > MultiMonitor.cpp
// Monitor.cpp : implementation file
//
//////////////////////////////////////////////////
// CMonitor - wrapper to Win32 multi-monitor API
//
// Author: Donald Kackman
// Email: don@itsEngineering.com
// Copyright 2002, Donald Kackman
//
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
//
///////////////////////////////////////////////////
#include "stdafx.h"
#include "MultiMonitor.h"
#include "Monitors.h"
// CMonitor
// constucts a monitor class not attached to any handle
CMonitor::CMonitor() : m_hMonitor( NULL )
{
}
// copy constructor
CMonitor::CMonitor( const CMonitor& monitor )
{
m_hMonitor = (HMONITOR)monitor;
}
CMonitor::~CMonitor()
{
}
void CMonitor::Attach( const HMONITOR hMonitor )
{
ASSERT( CMonitors::IsMonitor( hMonitor ) );
m_hMonitor = hMonitor;
}
HMONITOR CMonitor::Detach()
{
HMONITOR hMonitor = m_hMonitor;
m_hMonitor = NULL;
return hMonitor;
}
// creates an HDC for the monitor
// it is up to the client to call DeleteDC
//
// for normal multimonitor drawing it is not necessary to get a
// dc for each monitor. Windows takes care of drawing correctly
// on all monitors
//
// Only very exacting applications would need a DC for each monitor
HDC CMonitor::CreateDC() const
{
ASSERT( IsMonitor() );
CString name;
GetName( name );
//create a dc for this display
HDC hdc = ::CreateDC( name, name, NULL, NULL );
ASSERT( hdc != NULL );
//set the viewport based on the monitor rect's relation to the primary monitor
CRect rect;
GetMonitorRect( &rect );
::SetViewportOrgEx( hdc, -rect.left, -rect.top, NULL );
::SetViewportExtEx( hdc, rect.Width(), rect.Height(), NULL );
return hdc;
}
int CMonitor::GetBitsPerPixel() const
{
HDC hdc = CreateDC();
int ret = ::GetDeviceCaps( hdc, BITSPIXEL ) * ::GetDeviceCaps( hdc, PLANES );
VERIFY( ::DeleteDC( hdc ) );
return ret;
}
void CMonitor::GetName( CString& string ) const
{
ASSERT( IsMonitor() );
MONITORINFOEX mi;
mi.cbSize = sizeof( mi );
::GetMonitorInfo( m_hMonitor, &mi );
string = mi.szDevice;
}
//
// these methods return true if any part of the item intersects the monitor rect
BOOL CMonitor::IsOnMonitor( const POINT pt ) const
{
CRect rect;
GetMonitorRect( rect );
return rect.PtInRect( pt );
}
BOOL CMonitor::IsOnMonitor( const CWnd* pWnd ) const
{
CRect rect;
GetMonitorRect( rect );
ASSERT( ::IsWindow( pWnd->GetSafeHwnd() ) );
CRect wndRect;
pWnd->GetWindowRect( &wndRect );
return rect.IntersectRect( rect, wndRect );
}
BOOL CMonitor::IsOnMonitor( const LPRECT lprc ) const
{
CRect rect;
GetMonitorRect( rect );
return rect.IntersectRect( rect, lprc );
}
void CMonitor::GetMonitorRect( LPRECT lprc ) const
{
ASSERT( IsMonitor() );
MONITORINFO mi;
RECT rc;
mi.cbSize = sizeof( mi );
::GetMonitorInfo( m_hMonitor, &mi );
rc = mi.rcMonitor;
::SetRect( lprc, rc.left, rc.top, rc.right, rc.bottom );
}
//
// the work area does not include the start bar
void CMonitor::GetWorkAreaRect( LPRECT lprc ) const
{
ASSERT( IsMonitor() );
MONITORINFO mi;
RECT rc;
mi.cbSize = sizeof( mi );
::GetMonitorInfo( m_hMonitor, &mi );
rc = mi.rcWork;
::SetRect( lprc, rc.left, rc.top, rc.right, rc.bottom );
}
//these two center methods are adapted from David Campbell's
//MSJ article (see comment at the top of the header file)
void CMonitor::CenterRectToMonitor( LPRECT lprc, const BOOL UseWorkAreaRect ) const
{
int w = lprc->right - lprc->left;
int h = lprc->bottom - lprc->top;
CRect rect;
if ( UseWorkAreaRect )
GetWorkAreaRect( &rect );
else
GetMonitorRect( &rect );
lprc->left = rect.left + ( rect.Width() - w ) / 2;
lprc->top = rect.top + ( rect.Height() - h ) / 2;
lprc->right = lprc->left + w;
lprc->bottom = lprc->top + h;
}
void CMonitor::CenterWindowToMonitor( CWnd* const pWnd, const BOOL UseWorkAreaRect ) const
{
ASSERT( IsMonitor() );
ASSERT( pWnd );
ASSERT( ::IsWindow( pWnd->m_hWnd ) );
CRect rect;
pWnd->GetWindowRect( &rect );
CenterRectToMonitor( &rect, UseWorkAreaRect );
pWnd->SetWindowPos( NULL, rect.left, rect.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
}
void CMonitor::ClipRectToMonitor( LPRECT lprc, const BOOL UseWorkAreaRect ) const
{
int w = lprc->right - lprc->left;
int h = lprc->bottom - lprc->top;
CRect rect;
if ( UseWorkAreaRect )
GetWorkAreaRect( &rect );
else
GetMonitorRect( &rect );
lprc->left = max( rect.left, min( rect.right - w, lprc->left ) );
lprc->top = max( rect.top, min( rect.bottom - h, lprc->top ) );
lprc->right = lprc->left + w;
lprc->bottom = lprc->top + h;
}
//
// is the instance the primary monitor
BOOL CMonitor::IsPrimaryMonitor() const
{
ASSERT( IsMonitor() );
MONITORINFO mi;
mi.cbSize = sizeof( mi );
::GetMonitorInfo( m_hMonitor, &mi );
return mi.dwFlags == MONITORINFOF_PRIMARY;
}
//
// is the instance currently attached to a valid monitor handle
BOOL CMonitor::IsMonitor() const
{
return CMonitors::IsMonitor( m_hMonitor );
}