Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / WinForms / Managed / System / WinForms / Screen.cs / 1 / Screen.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
/*
*/
namespace System.Windows.Forms {
using System.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using Microsoft.Win32;
///
///
///
/// Represents a display device or
/// multiple display devices on a single system.
///
///
public class Screen {
readonly IntPtr hmonitor;
///
/// Bounds of the screen
///
readonly Rectangle bounds;
///
/// Available working area on the screen. This excludes taskbars and other
/// docked windows.
///
private Rectangle workingArea = Rectangle.Empty;
///
/// Set to true if this screen is the primary monitor
///
readonly bool primary;
///
/// Device name associated with this monitor
///
readonly string deviceName;
readonly int bitDepth;
private static object syncLock = new object();//used to lock this class before sync'ing to SystemEvents
private static int desktopChangedCount = -1;//static counter of desktop size changes
private int currentDesktopChangedCount = -1;//instance-based counter used to invalidate WorkingArea
// This identifier is just for us, so that we don't try to call the multimon
// functions if we just need the primary monitor... this is safer for
// non-multimon OSes.
//
private const int PRIMARY_MONITOR = unchecked((int)0xBAADF00D);
private const int MONITOR_DEFAULTTONULL = 0x00000000;
private const int MONITOR_DEFAULTTOPRIMARY = 0x00000001;
private const int MONITOR_DEFAULTTONEAREST = 0x00000002;
private const int MONITORINFOF_PRIMARY = 0x00000001;
private static bool multiMonitorSupport = (UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CMONITORS) != 0);
private static Screen[] screens;
internal Screen(IntPtr monitor) : this(monitor, IntPtr.Zero) {
}
internal Screen(IntPtr monitor, IntPtr hdc) {
IntPtr screenDC = hdc;
if (!multiMonitorSupport || monitor == (IntPtr)PRIMARY_MONITOR) {
// Single monitor system
//
bounds = SystemInformation.VirtualScreen;
primary = true;
deviceName = "DISPLAY";
}
else {
// MultiMonitor System
// We call the 'A' version of GetMonitorInfoA() because
// the 'W' version just never fills out the struct properly on Win2K.
//
NativeMethods.MONITORINFOEX info = new NativeMethods.MONITORINFOEX();
SafeNativeMethods.GetMonitorInfo(new HandleRef(null, monitor), info);
bounds = Rectangle.FromLTRB(info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right, info.rcMonitor.bottom);
primary = ((info.dwFlags & MONITORINFOF_PRIMARY) != 0);
int count = info.szDevice.Length;
while (count > 0 && info.szDevice[count - 1] == (char)0) {
count--;
}
deviceName = new string(info.szDevice);
deviceName = deviceName.TrimEnd((char)0);
if (hdc == IntPtr.Zero) {
screenDC = UnsafeNativeMethods.CreateDC(deviceName);
}
}
hmonitor = monitor;
this.bitDepth = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, screenDC), NativeMethods.BITSPIXEL);
this.bitDepth *= UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, screenDC), NativeMethods.PLANES);
if (hdc != screenDC) {
UnsafeNativeMethods.DeleteDC(new HandleRef(null, screenDC));
}
}
///
///
///
/// Gets an array of all of the displays on the system.
///
///
public static Screen[] AllScreens {
get {
if (screens == null) {
if (multiMonitorSupport) {
MonitorEnumCallback closure = new MonitorEnumCallback();
NativeMethods.MonitorEnumProc proc = new NativeMethods.MonitorEnumProc(closure.Callback);
IntPtr hdc = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef);
try {
SafeNativeMethods.EnumDisplayMonitors(new HandleRef(null, hdc), null, proc, IntPtr.Zero);
}
finally {
UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, hdc));
}
if (closure.screens.Count > 0) {
Screen[] temp = new Screen[closure.screens.Count];
closure.screens.CopyTo(temp, 0);
screens = temp;
}
else {
screens = new Screen[] {new Screen((IntPtr)PRIMARY_MONITOR)};
}
}
else {
screens = new Screen[] {PrimaryScreen};
}
// Now that we have our screens, attach a display setting changed
// event so that we know when to invalidate them.
//
SystemEvents.DisplaySettingsChanging += new EventHandler(OnDisplaySettingsChanging);
}
return screens;
}
}
///
///
///
/// Gets Bits per Pixel value.
///
///
public int BitsPerPixel {
get {
return bitDepth;
}
}
///
///
///
/// Gets the bounds of the display.
///
///
public Rectangle Bounds {
get {
return bounds;
}
}
///
///
///
/// Gets the device name associated with a display.
///
///
public string DeviceName {
get {
return deviceName;
}
}
///
///
///
/// Gets a value indicating whether a particular display is
/// the primary device.
///
///
public bool Primary {
get {
return primary;
}
}
///
///
///
/// Gets the
/// primary display.
///
///
public static Screen PrimaryScreen {
get {
if (multiMonitorSupport) {
Screen[] screens = AllScreens;
for (int i=0; i
///
///
/// Gets the working area of the screen.
///
///
public Rectangle WorkingArea {
get {
//if the static Screen class has a different desktop change count
//than this instance then update the count and recalculate our working area
if (currentDesktopChangedCount != Screen.DesktopChangedCount) {
Interlocked.Exchange(ref currentDesktopChangedCount, Screen.DesktopChangedCount);
if (!multiMonitorSupport ||hmonitor == (IntPtr)PRIMARY_MONITOR) {
// Single monitor system
//
workingArea = SystemInformation.WorkingArea;
}
else {
// MultiMonitor System
// We call the 'A' version of GetMonitorInfoA() because
// the 'W' version just never fills out the struct properly on Win2K.
//
NativeMethods.MONITORINFOEX info = new NativeMethods.MONITORINFOEX();
SafeNativeMethods.GetMonitorInfo(new HandleRef(null, hmonitor), info);
workingArea = Rectangle.FromLTRB(info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom);
}
}
return workingArea;
}
}
///
/// Screen instances call this property to determine
/// if their WorkingArea cache needs to be invalidated.
///
private static int DesktopChangedCount {
get {
if (desktopChangedCount == -1) {
lock (syncLock) {
//now that we have a lock, verify (again) our changecount...
if (desktopChangedCount == -1) {
//sync the UserPreference.Desktop change event. We'll keep count
//of desktop changes so that the WorkingArea property on Screen
//instances know when to invalidate their cache.
SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(OnUserPreferenceChanged);
desktopChangedCount = 0;
}
}
}
return desktopChangedCount;
}
}
///
///
///
/// Specifies a value that indicates whether the specified object is equal to
/// this one.
///
///
public override bool Equals(object obj) {
if (obj is Screen) {
Screen comp = (Screen)obj;
if (hmonitor == comp.hmonitor) {
return true;
}
}
return false;
}
///
///
///
/// Retrieves a
/// for the monitor that contains the specified point.
///
///
///
public static Screen FromPoint(Point point) {
if (multiMonitorSupport) {
NativeMethods.POINTSTRUCT pt = new NativeMethods.POINTSTRUCT(point.X, point.Y);
return new Screen(SafeNativeMethods.MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST));
}
else {
return new Screen((IntPtr)PRIMARY_MONITOR);
}
}
///
///
///
/// Retrieves a
/// for the monitor that contains the
/// largest region of the rectangle.
///
///
///
public static Screen FromRectangle(Rectangle rect) {
if (multiMonitorSupport) {
NativeMethods.RECT rc = NativeMethods.RECT.FromXYWH(rect.X, rect.Y, rect.Width, rect.Height);
return new Screen(SafeNativeMethods.MonitorFromRect(ref rc, MONITOR_DEFAULTTONEAREST));
}
else {
return new Screen((IntPtr)PRIMARY_MONITOR, IntPtr.Zero);
}
}
///
///
///
/// Retrieves a
/// for the monitor that contains the largest
/// region of the window of the control.
///
///
public static Screen FromControl(Control control) {
return FromHandleInternal(control.Handle);
}
///
///
///
/// Retrieves a
/// for the monitor that
/// contains the largest region of the window.
///
///
public static Screen FromHandle(IntPtr hwnd) {
Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "ObjectFromWin32Handle Demanded");
IntSecurity.ObjectFromWin32Handle.Demand();
return FromHandleInternal(hwnd);
}
internal static Screen FromHandleInternal(IntPtr hwnd) {
if (multiMonitorSupport) {
return new Screen(SafeNativeMethods.MonitorFromWindow(new HandleRef(null, hwnd), MONITOR_DEFAULTTONEAREST));
}
else {
return new Screen((IntPtr)PRIMARY_MONITOR, IntPtr.Zero);
}
}
///
///
///
/// Retrieves the working area for the monitor that is closest to the
/// specified point.
///
///
///
public static Rectangle GetWorkingArea(Point pt) {
return Screen.FromPoint(pt).WorkingArea;
}
///
///
///
/// Retrieves the working area for the monitor that contains the largest region
/// of the specified rectangle.
///
///
///
public static Rectangle GetWorkingArea(Rectangle rect) {
return Screen.FromRectangle(rect).WorkingArea;
}
///
///
///
/// Retrieves the working area for the monitor that contains the largest
/// region of the specified control.
///
///
///
public static Rectangle GetWorkingArea(Control ctl) {
return Screen.FromControl(ctl).WorkingArea;
}
///
///
///
/// Retrieves the bounds of the monitor that is closest to the specified
/// point.
///
///
public static Rectangle GetBounds(Point pt) {
return Screen.FromPoint(pt).Bounds;
}
///
///
///
/// Retrieves the bounds of the monitor that contains the largest region of the
/// specified rectangle.
///
///
public static Rectangle GetBounds(Rectangle rect) {
return Screen.FromRectangle(rect).Bounds;
}
///
///
///
/// Retrieves the bounds of the monitor
/// that contains the largest region of the specified control.
///
///
public static Rectangle GetBounds(Control ctl) {
return Screen.FromControl(ctl).Bounds;
}
///
///
///
/// Computes and retrieves a hash code for an object.
///
///
public override int GetHashCode() {
return(int)hmonitor;
}
///
/// Called by the SystemEvents class when our display settings are
/// changing. We cache screen information and at this point we must
/// invalidate our cache.
///
private static void OnDisplaySettingsChanging(object sender, EventArgs e) {
// Now that we've responded to this event, we don't need it again until
// someone re-queries. We will re-add the event at that time.
//
SystemEvents.DisplaySettingsChanging -= new EventHandler(OnDisplaySettingsChanging);
// Display settings changed, so the set of screens we have is invalid.
//
screens = null;
}
///
/// Called by the SystemEvents class when our display settings have
/// changed. Here, we increment a static counter that Screen instances
/// can check against to invalidate their cache.
///
private static void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) {
if (e.Category == UserPreferenceCategory.Desktop) {
Interlocked.Increment(ref desktopChangedCount);
}
}
///
///
///
/// Retrieves a string representing this object.
///
///
public override string ToString() {
return GetType().Name + "[Bounds=" + bounds.ToString() + " WorkingArea=" + WorkingArea.ToString() + " Primary=" + primary.ToString() + " DeviceName=" + deviceName;
}
///
///
///
private class MonitorEnumCallback {
public ArrayList screens = new ArrayList();
public virtual bool Callback(IntPtr monitor, IntPtr hdc, IntPtr lprcMonitor, IntPtr lparam) {
screens.Add(new Screen(monitor, hdc));
return true;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DynamicPropertyReader.cs
- ReadOnlyDictionary.cs
- ListenerElementsCollection.cs
- XmlSchemaSimpleType.cs
- ColumnMap.cs
- ComboBoxRenderer.cs
- MasterPageParser.cs
- DoubleLink.cs
- DbConnectionPoolIdentity.cs
- NavigateEvent.cs
- dtdvalidator.cs
- ItemCollection.cs
- DataControlFieldHeaderCell.cs
- TypeResolvingOptionsAttribute.cs
- DataGridViewCellEventArgs.cs
- Rules.cs
- ScriptResourceInfo.cs
- EventLogTraceListener.cs
- QueryOpcode.cs
- CompressionTransform.cs
- DesignOnlyAttribute.cs
- WorkflowNamespace.cs
- HostExecutionContextManager.cs
- XpsFixedDocumentSequenceReaderWriter.cs
- SamlSerializer.cs
- ExpressionBindingCollection.cs
- FamilyTypeface.cs
- XmlWriterTraceListener.cs
- DesignerAutoFormat.cs
- SeekStoryboard.cs
- Misc.cs
- ModifiableIteratorCollection.cs
- DataBindingExpressionBuilder.cs
- TagMapCollection.cs
- XmlILAnnotation.cs
- SqlProcedureAttribute.cs
- UrlParameterWriter.cs
- SubclassTypeValidatorAttribute.cs
- ParentControlDesigner.cs
- InternalTransaction.cs
- DecoderFallback.cs
- SyndicationDeserializer.cs
- Pen.cs
- WebPartConnectionsConfigureVerb.cs
- DesignTimeValidationFeature.cs
- DeviceContexts.cs
- DataGridCommandEventArgs.cs
- _ProxyRegBlob.cs
- PersonalizableTypeEntry.cs
- Tracer.cs
- util.cs
- ColorTransformHelper.cs
- MsmqPoisonMessageException.cs
- CatalogPartChrome.cs
- ToolStripHighContrastRenderer.cs
- HttpModuleAction.cs
- PropertyRecord.cs
- TemplateField.cs
- Pointer.cs
- AsymmetricSignatureDeformatter.cs
- NameSpaceEvent.cs
- XsltQilFactory.cs
- EntityKeyElement.cs
- DataSet.cs
- MetaTable.cs
- XmlSchemaProviderAttribute.cs
- XmlnsCompatibleWithAttribute.cs
- InvalidCardException.cs
- BindingMemberInfo.cs
- BasicHttpSecurityMode.cs
- Soap.cs
- VisualStyleInformation.cs
- HttpConfigurationSystem.cs
- DataGridCaption.cs
- ObjectQueryState.cs
- Control.cs
- StreamResourceInfo.cs
- XmlReflectionImporter.cs
- BuildProviderUtils.cs
- InvalidPrinterException.cs
- JumpPath.cs
- SqlTrackingQuery.cs
- SqlDataSourceCommandParser.cs
- QilValidationVisitor.cs
- ReachDocumentSequenceSerializer.cs
- StaticResourceExtension.cs
- MatrixCamera.cs
- UnsafeNativeMethods.cs
- IOException.cs
- UpdateException.cs
- OpenTypeLayout.cs
- ObsoleteAttribute.cs
- ChannelCredentials.cs
- StoreItemCollection.cs
- LocalValueEnumerator.cs
- SystemWebCachingSectionGroup.cs
- PageContent.cs
- CheckedPointers.cs
- XPathSelfQuery.cs
- OdbcPermission.cs