Introduction
Awhile back I decided to
write a screensaver
application as a way to pick
up
MFC. After I got
my first implementation up
and running I shipped it off
to a friend. Well the first
thing he noted was a a
glaring bug: he uses
multiple monitors
and my screen saver only
showed up on one.
After some scouring of
the internet and research
into MSDN I was able to to
get the screensaver running
on
multiple monitors
by using some API calls the
were introduced with Windows
98/2000. This project is a
couple of small
MFC
classes that wrap the
multiple-monitor
API.
These classes can be
safely used on Windows
95/NT4 as well. On those
platforms, they just provide
the properties of the one
and only monitor.
Background
Eveyrything you ever
wanted to know about the API
for
multiple monitors
is described in a very well
written
article by David Campbell
in the June 1997 issue of
MSJ.
The API itself is simple
and straightforward. It has
some new constants to pass
to
GetSystemMetrics
and a couple methods to
enumerate all of the
monitors currently attached
to the system and get the
properties of a given
monitor.
All of the types and
functions are defined by the
platform SDK in the file
multimon.h
. If
you
#define WINVER
to be greater than
0x400
you don't need
to link to
multimon.h
,
as the API gets defined in
windef.h for Windows 98 and
later targeted builds. Multimon.h
also provides some stub
functions that allow calls
to be safely made on Windows
95/NT4 machines. These
wrappers interrogate the
runtime OS and either make
fall-through calls into the
actual API or return the
propeties of the one (and
only)
monitor on
those older platforms.
The
multiple monitor
classes take care of
including
multimon.h
correctly depending on the
value of
WINVER
.
Using the code
CMointor
is
a basic
MFC
class that allows you to
safely use the
multiple-monitor
API on any Win32 platform.
There are three classes
in this library:
CMonitors
represents the collection of
monitors
currently attached to the
system and wraps the
EnumDisplayMonitors
API function.
Collapse
Copy Code
CMonitor GetMonitor( const int index ) const;
int GetCount() const;
static CMonitor GetNearestMonitor( const LPRECT lprc );
static CMonitor GetNearestMonitor( const POINT pt );
static CMonitor GetNearestMonitor( const CWnd* pWnd );
static BOOL IsOnScreen( const POINT pt );
static BOOL IsOnScreen( const CWnd* pWnd );
static BOOL IsOnScreen( const LPRECT lprc );
static void GetVirtualDesktopRect( LPRECT lprc );
static BOOL IsMonitor( const HMONITOR hMonitor );
static CMonitor GetPrimaryMonitor();
static BOOL AllMonitorsShareDisplayFormat();
static int GetMonitorCount();
CMonitor
is
a wrapper around an
HMONITOR
handle
(returned from
EnumDisplayMonitors
)
and the
GetMonitorInfo
function. With
CMonitor
you can get
at the characteristics of a
given monitor.
Collapse
Copy Code
void Attach( const HMONITOR hMonitor );
HMONITOR Detach();
void ClipRectToMonitor( LPRECT lprc,
const BOOL UseWorkAreaRect = FALSE ) const;
void CenterRectToMonitor( LPRECT lprc,
const BOOL UseWorkAreaRect = FALSE ) const;
void CenterWindowToMonitor( CWnd* const pWnd,
const BOOL UseWorkAreaRect = FALSE ) const;
HDC CreateDC() const;
void GetMonitorRect( LPRECT lprc ) const;
void GetWorkAreaRect( LPRECT lprc ) const;
void GetName( CString& string ) const;
int GetBitsPerPixel() const;
BOOL IsOnMonitor( const POINT pt ) const;
BOOL IsOnMonitor( const CWnd* pWnd ) const;
BOOL IsOnMonitor( const LPRECT lprc ) const;
BOOL IsPrimaryMonitor() const;
BOOL IsMonitor() const;
CMonitorDC
is a
CDC
derived class that
represents a monitor
specific device context. I
haven't really gone to far
with this class but it
seemed like a logical part
of the library.
Known Limitations
CMonitor
and
CMonitors
rely
on the assumption that a
monitor handle
does not change. This has
proved to be a safe
assumption empirically but
isn't nessecarily a
guarantee.