Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / CommonUI / System / Drawing / Pen.cs / 2 / Pen.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Drawing { using System.Runtime.InteropServices; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System; using System.Internal; using Microsoft.Win32; using System.ComponentModel; using System.Drawing.Drawing2D; using System.Drawing.Internal; using System.Globalization; ////// /// public sealed class Pen : MarshalByRefObject, ISystemColorTracker, ICloneable, IDisposable { #if FINALIZATION_WATCH private string allocationSite = Graphics.GetAllocationStack(); #endif // handle to native GDI+ pen object. private IntPtr nativePen; // GDI+ doesn't understand system colors, so we need to cache the value here private Color color; private bool immutable; ////// Defines an object used to draw lines and curves. /// ////// Creates a Pen from a native GDI+ object. /// private Pen(IntPtr nativePen) { SetNativePen( nativePen ); } internal Pen(Color color, bool immutable) : this(color) { this.immutable = immutable; } ////// /// public Pen(Color color) : this(color, (float)1.0) { } ////// Initializes a new instance of the Pen /// class with the specified ///. /// /// /// public Pen(Color color, float width) { this.color = color; IntPtr pen = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipCreatePen1(color.ToArgb(), width, (int)GraphicsUnit.World, out pen); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); SetNativePen(pen); if (this.color.IsSystemColor) { SystemColorTracker.Add(this); } } ////// Initializes a new instance of the ///class with the specified /// and . /// /// /// public Pen(Brush brush) : this(brush, (float)1.0) { } ////// Initializes a new instance of the Pen class with the /// specified ///. /// /// /// public Pen(Brush brush, float width) { IntPtr pen = IntPtr.Zero; if (brush == null) throw new ArgumentNullException("brush"); int status = SafeNativeMethods.Gdip.GdipCreatePen2(new HandleRef(brush, brush.NativeBrush), width, (int)GraphicsUnit.World, out pen); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); SetNativePen(pen); } internal void SetNativePen(IntPtr nativePen) { if (nativePen == IntPtr.Zero) { throw new ArgumentNullException("nativePen"); } this.nativePen = nativePen; } ////// Initializes a new instance of the ///class with /// the specified and width. /// /// Gets the GDI+ native object. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal IntPtr NativePen { get { //Need to comment this line out to allow for checking this.NativePen == IntPtr.Zero. //Debug.Assert(this.nativePen != IntPtr.Zero, "this.nativePen == null." ); return this.nativePen; } } /** * Create a copy of the pen object */ ////// /// Creates an exact copy of this public object Clone() { IntPtr clonePen = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipClonePen(new HandleRef(this, this.NativePen), out clonePen); if (status != SafeNativeMethods.Gdip.Ok) { throw SafeNativeMethods.Gdip.StatusException(status); } return new Pen(clonePen); } /** * Dispose of resources associated with the Pen object */ ///. /// /// /// Cleans up Windows resources for this public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } void Dispose(bool disposing) { #if FINALIZATION_WATCH if (!disposing && nativePen != IntPtr.Zero) Debug.WriteLine("**********************\nDisposed through finalization:\n" + allocationSite); #endif if (!disposing) { // If we are finalizing, then we will be unreachable soon. Finalize calls dispose to // release resources, so we must make sure that during finalization we are // not immutable. // immutable = false; } else if (immutable) { throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Brush")); } if (this.nativePen != IntPtr.Zero) { try{ #if DEBUG int status = #endif SafeNativeMethods.Gdip.GdipDeletePen(new HandleRef(this, this.NativePen)); #if DEBUG Debug.Assert(status == SafeNativeMethods.Gdip.Ok, "GDI+ returned an error status: " + status.ToString(CultureInfo.InvariantCulture)); #endif } catch( Exception ex ){ if(ClientUtils.IsSecurityOrCriticalException( ex ) ) { throw; } Debug.Fail( "Exception thrown during Dispose: " + ex.ToString() ); } finally{ this.nativePen = IntPtr.Zero; } } } ///. /// /// /// Cleans up Windows resources for this ~Pen() { Dispose(false); } /** * Set/get pen width */ ///. /// /// /// Gets or sets the width of this public float Width { get { float[] width = new float[] { 0}; int status = SafeNativeMethods.Gdip.GdipGetPenWidth(new HandleRef(this, this.NativePen), width); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return width[0]; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenWidth(new HandleRef(this, this.NativePen), value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get line caps: start, end, and dash */ ///. /// /// /// public void SetLineCap(LineCap startCap, LineCap endCap, DashCap dashCap) { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenLineCap197819(new HandleRef(this, this.NativePen), (int)startCap, (int)endCap, (int)dashCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ////// Sets the values that determine the style of /// cap used to end lines drawn by this ///. /// /// /// public LineCap StartCap { get { int startCap = 0; int status = SafeNativeMethods.Gdip.GdipGetPenStartCap(new HandleRef(this, this.NativePen), out startCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(LineCap) startCap; } set { //validate the enum value switch(value) { case LineCap.Flat: case LineCap.Square: case LineCap.Round: case LineCap.Triangle: case LineCap.NoAnchor: case LineCap.SquareAnchor: case LineCap.RoundAnchor: case LineCap.DiamondAnchor: case LineCap.ArrowAnchor: case LineCap.AnchorMask: case LineCap.Custom: break; default: throw new InvalidEnumArgumentException("value", (int)value, typeof(LineCap)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenStartCap(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// Gets or sets the cap style used at the /// beginning of lines drawn with this ///. /// /// /// public LineCap EndCap { get { int endCap = 0; int status = SafeNativeMethods.Gdip.GdipGetPenEndCap(new HandleRef(this, this.NativePen), out endCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(LineCap) endCap; } set { //validate the enum value switch(value) { case LineCap.Flat: case LineCap.Square: case LineCap.Round: case LineCap.Triangle: case LineCap.NoAnchor: case LineCap.SquareAnchor: case LineCap.RoundAnchor: case LineCap.DiamondAnchor: case LineCap.ArrowAnchor: case LineCap.AnchorMask: case LineCap.Custom: break; default: throw new InvalidEnumArgumentException("value", (int)value, typeof(LineCap)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenEndCap(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// Gets or sets the cap style used at the end of /// lines drawn with this ///. /// /// /// Gets or sets the cap style used at the /// beginning or end of dashed lines drawn with this public DashCap DashCap { get { int dashCap = 0; int status = SafeNativeMethods.Gdip.GdipGetPenDashCap197819(new HandleRef(this, this.NativePen), out dashCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(DashCap)dashCap; } set { //validate the enum value if (!ClientUtils.IsEnumValid_NotSequential(value, (int)value, (int)DashCap.Flat, (int)DashCap.Round, (int)DashCap.Triangle)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(DashCap)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenDashCap197819(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get line join */ ///. /// /// /// Gets or sets the join style for the ends of /// two overlapping lines drawn with this public LineJoin LineJoin { get { int lineJoin = 0; int status = SafeNativeMethods.Gdip.GdipGetPenLineJoin(new HandleRef(this, this.NativePen), out lineJoin); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(LineJoin)lineJoin; } set { //valid values are 0x0 to 0x3 if (!ClientUtils.IsEnumValid(value, (int)value, (int)LineJoin.Miter, (int)LineJoin.MiterClipped)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(LineJoin)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenLineJoin(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get custom start line cap */ ///. /// /// /// public CustomLineCap CustomStartCap { get { IntPtr lineCap = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipGetPenCustomStartCap(new HandleRef(this, this.NativePen), out lineCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return CustomLineCap.CreateCustomLineCapObject(lineCap); } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenCustomStartCap(new HandleRef(this, this.NativePen), new HandleRef(value, (value == null) ? IntPtr.Zero : value.nativeCap)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get custom end line cap */ ////// Gets or sets a custom cap style to use at the beginning of lines /// drawn with this ///. /// /// /// public CustomLineCap CustomEndCap { get { IntPtr lineCap = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipGetPenCustomEndCap(new HandleRef(this, this.NativePen), out lineCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return CustomLineCap.CreateCustomLineCapObject(lineCap); } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenCustomEndCap(new HandleRef(this, this.NativePen), new HandleRef(value, (value == null) ? IntPtr.Zero : value.nativeCap)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// Gets or sets a custom cap style to use at the end of lines /// drawn with this ///. /// /// /// Gets or sets the limit of the thickness of /// the join on a mitered corner. /// public float MiterLimit { get { float[] miterLimit = new float[] { 0}; int status = SafeNativeMethods.Gdip.GdipGetPenMiterLimit(new HandleRef(this, this.NativePen), miterLimit); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return miterLimit[0]; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenMiterLimit(new HandleRef(this, this.NativePen), value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Pen Mode */ ////// /// public PenAlignment Alignment { get { PenAlignment penMode = 0; int status = SafeNativeMethods.Gdip.GdipGetPenMode(new HandleRef(this, this.NativePen), out penMode); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(PenAlignment) penMode; } set { //validate the enum value //valid values are 0x0 to 0x4 if (!ClientUtils.IsEnumValid(value, (int)value, (int)PenAlignment.Center, (int)PenAlignment.Right)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(PenAlignment)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenMode(new HandleRef(this, this.NativePen), value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get pen transform */ ////// Gets or sets /// the alignment for objects drawn with this ///. /// /// /// public Matrix Transform { get { Matrix matrix = new Matrix(); int status = SafeNativeMethods.Gdip.GdipGetPenTransform(new HandleRef(this, this.NativePen), new HandleRef(matrix, matrix.nativeMatrix)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return matrix; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); if (value == null) { throw new ArgumentNullException("value"); } int status = SafeNativeMethods.Gdip.GdipSetPenTransform(new HandleRef(this, this.NativePen), new HandleRef(value, value.nativeMatrix)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// Gets /// or sets the geometrical transform for objects drawn with this ///. /// /// /// Resets the geometric transform for this /// public void ResetTransform() { int status = SafeNativeMethods.Gdip.GdipResetPenTransform(new HandleRef(this, this.NativePen)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ///to /// identity. /// /// /// public void MultiplyTransform(Matrix matrix) { MultiplyTransform(matrix, MatrixOrder.Prepend); } ////// Multiplies the transform matrix for this /// ///by /// the specified . /// /// /// public void MultiplyTransform(Matrix matrix, MatrixOrder order) { int status = SafeNativeMethods.Gdip.GdipMultiplyPenTransform(new HandleRef(this, this.NativePen), new HandleRef(matrix, matrix.nativeMatrix), order); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ////// Multiplies the transform matrix for this /// ///by /// the specified in the specified order. /// /// /// public void TranslateTransform(float dx, float dy) { TranslateTransform(dx, dy, MatrixOrder.Prepend); } ////// Translates the local geometrical transform /// by the specified dimmensions. This method prepends the translation to the /// transform. /// ////// /// Translates the local geometrical transform /// by the specified dimmensions in the specified order. /// public void TranslateTransform(float dx, float dy, MatrixOrder order) { int status = SafeNativeMethods.Gdip.GdipTranslatePenTransform(new HandleRef(this, this.NativePen), dx, dy, order); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ////// /// Scales the local geometric transform by the /// specified amounts. This method prepends the scaling matrix to the transform. /// public void ScaleTransform(float sx, float sy) { ScaleTransform(sx, sy, MatrixOrder.Prepend); } ////// /// public void ScaleTransform(float sx, float sy, MatrixOrder order) { int status = SafeNativeMethods.Gdip.GdipScalePenTransform(new HandleRef(this, this.NativePen), sx, sy, order); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ////// Scales the local geometric transform by the /// specified amounts in the specified order. /// ////// /// Rotates the local geometric transform by the /// specified amount. This method prepends the rotation to the transform. /// public void RotateTransform(float angle) { RotateTransform(angle, MatrixOrder.Prepend); } ////// /// public void RotateTransform(float angle, MatrixOrder order) { int status = SafeNativeMethods.Gdip.GdipRotatePenTransform(new HandleRef(this, this.NativePen), angle, order); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } /** * Set/get pen type (color, line texture, or brush) * * @notes GetLineFill returns either a Brush object * or a LineTexture object. */ private void InternalSetColor(Color value) { int status = SafeNativeMethods.Gdip.GdipSetPenColor(new HandleRef(this, this.NativePen), color.ToArgb()); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); this.color = value; } ////// Rotates the local geometric transform by the specified /// amount in the specified order. /// ////// /// Gets the style of lines drawn with this /// public PenType PenType { get { int type = -1; int status = SafeNativeMethods.Gdip.GdipGetPenFillType(new HandleRef(this, this.NativePen), out type); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(PenType)type; } } ///. /// /// /// public Color Color { get { if (color == Color.Empty) { int colorARGB = 0; int status = SafeNativeMethods.Gdip.GdipGetPenColor(new HandleRef(this, this.NativePen), out colorARGB); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); this.color = Color.FromArgb(colorARGB); } // GDI+ doesn't understand system colors, so we can't use GdipGetPenColor in the general case return this.color; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); if( value != this.color ) { Color oldColor = this.color; this.color = value; InternalSetColor(value); // if (value.IsSystemColor && !oldColor.IsSystemColor) SystemColorTracker.Add(this); } } } ////// Gets or sets the color of this ///. /// /// /// Gets or sets the public Brush Brush { get { Brush brush = null; switch (PenType) { case PenType.SolidColor: brush = new SolidBrush(GetNativeBrush()); break; case PenType.HatchFill: brush = new HatchBrush(GetNativeBrush()); break; case PenType.TextureFill: brush = new TextureBrush(GetNativeBrush()); break; case PenType.PathGradient: brush = new PathGradientBrush(GetNativeBrush()); break; case PenType.LinearGradient: brush = new LinearGradientBrush(GetNativeBrush()); break; default: break; } return brush; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); if (value == null) throw new ArgumentNullException("value"); int status = SafeNativeMethods.Gdip.GdipSetPenBrushFill(new HandleRef(this, this.NativePen), new HandleRef(value, value.NativeBrush)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } private IntPtr GetNativeBrush() { IntPtr nativeBrush = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipGetPenBrushFill(new HandleRef(this, this.NativePen), out nativeBrush); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return nativeBrush; } /** * Set/get dash attributes */ ///that /// determines attributes of this . /// /// /// Gets or sets the style used for dashed /// lines drawn with this public DashStyle DashStyle { get { int dashstyle = 0; int status = SafeNativeMethods.Gdip.GdipGetPenDashStyle(new HandleRef(this, this.NativePen), out dashstyle); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(DashStyle) dashstyle; } set { //valid values are 0x0 to 0x5 if (!ClientUtils.IsEnumValid(value, (int)value, (int)DashStyle.Solid, (int)DashStyle.Custom)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(DashStyle)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenDashStyle(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) { throw SafeNativeMethods.Gdip.StatusException(status); } //if we just set pen style to "custom" without defining the custom dash pattern, //lets make sure we can return a valid value... // if (value == DashStyle.Custom) { EnsureValidDashPattern(); } } } ///. /// /// /// This method is called after the user sets the pen's dash style to custom. /// Here, we make sure that there is a default value set for the custom pattern. /// private void EnsureValidDashPattern() { int retval = 0; int status = SafeNativeMethods.Gdip.GdipGetPenDashCount(new HandleRef(this, this.NativePen), out retval); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); if (retval == 0) { //just set to a solid pattern DashPattern = new float[]{1}; } } ////// /// Gets or sets the distance from the start of /// a line to the beginning of a dash pattern. /// public float DashOffset { get { float[] dashoffset = new float[] { 0}; int status = SafeNativeMethods.Gdip.GdipGetPenDashOffset(new HandleRef(this, this.NativePen), dashoffset); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return dashoffset[0]; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenDashOffset(new HandleRef(this, this.NativePen), value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// /// public float[] DashPattern { get { float[] dashArray; // Figure out how many dash elements we have int retval = 0; int status = SafeNativeMethods.Gdip.GdipGetPenDashCount(new HandleRef(this, this.NativePen), out retval); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); int count = retval; // Allocate temporary native memory buffer // and pass it to GDI+ to retrieve dash array elements IntPtr buf = Marshal.AllocHGlobal(4 * count); status = SafeNativeMethods.Gdip.GdipGetPenDashArray(new HandleRef(this, this.NativePen), buf, count); try { if (status != SafeNativeMethods.Gdip.Ok) { throw SafeNativeMethods.Gdip.StatusException(status); } dashArray = new float[count]; Marshal.Copy(buf, dashArray, 0, count); } finally { Marshal.FreeHGlobal(buf); } return dashArray; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); //validate the DashPattern value being set if (value == null || value.Length == 0) { throw new ArgumentException(SR.GetString(SR.InvalidDashPattern)); } int count = value.Length; IntPtr buf = Marshal.AllocHGlobal(4 * count); try { Marshal.Copy(value, 0, buf, count); int status = SafeNativeMethods.Gdip.GdipSetPenDashArray(new HandleRef(this, this.NativePen), new HandleRef(buf, buf), count); if (status != SafeNativeMethods.Gdip.Ok){ throw SafeNativeMethods.Gdip.StatusException(status); } } finally { Marshal.FreeHGlobal(buf); } } } ////// Gets or sets an array of cutom dashes and /// spaces. The dashes are made up of line segments. /// ////// /// Gets or sets an array of cutom dashes and /// spaces. The dashes are made up of line segments. /// public float[] CompoundArray { get { int count = 0; int status = SafeNativeMethods.Gdip.GdipGetPenCompoundCount(new HandleRef(this, this.NativePen), out count); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); float[] array = new float[count]; status = SafeNativeMethods.Gdip.GdipGetPenCompoundArray(new HandleRef(this, this.NativePen), array, count); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return array; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenCompoundArray(new HandleRef(this, this.NativePen), value, value.Length); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// void ISystemColorTracker.OnSystemColorChanged() { if (this.NativePen != IntPtr.Zero) InternalSetColor(color); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Drawing { using System.Runtime.InteropServices; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System; using System.Internal; using Microsoft.Win32; using System.ComponentModel; using System.Drawing.Drawing2D; using System.Drawing.Internal; using System.Globalization; ////// /// public sealed class Pen : MarshalByRefObject, ISystemColorTracker, ICloneable, IDisposable { #if FINALIZATION_WATCH private string allocationSite = Graphics.GetAllocationStack(); #endif // handle to native GDI+ pen object. private IntPtr nativePen; // GDI+ doesn't understand system colors, so we need to cache the value here private Color color; private bool immutable; ////// Defines an object used to draw lines and curves. /// ////// Creates a Pen from a native GDI+ object. /// private Pen(IntPtr nativePen) { SetNativePen( nativePen ); } internal Pen(Color color, bool immutable) : this(color) { this.immutable = immutable; } ////// /// public Pen(Color color) : this(color, (float)1.0) { } ////// Initializes a new instance of the Pen /// class with the specified ///. /// /// /// public Pen(Color color, float width) { this.color = color; IntPtr pen = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipCreatePen1(color.ToArgb(), width, (int)GraphicsUnit.World, out pen); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); SetNativePen(pen); if (this.color.IsSystemColor) { SystemColorTracker.Add(this); } } ////// Initializes a new instance of the ///class with the specified /// and . /// /// /// public Pen(Brush brush) : this(brush, (float)1.0) { } ////// Initializes a new instance of the Pen class with the /// specified ///. /// /// /// public Pen(Brush brush, float width) { IntPtr pen = IntPtr.Zero; if (brush == null) throw new ArgumentNullException("brush"); int status = SafeNativeMethods.Gdip.GdipCreatePen2(new HandleRef(brush, brush.NativeBrush), width, (int)GraphicsUnit.World, out pen); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); SetNativePen(pen); } internal void SetNativePen(IntPtr nativePen) { if (nativePen == IntPtr.Zero) { throw new ArgumentNullException("nativePen"); } this.nativePen = nativePen; } ////// Initializes a new instance of the ///class with /// the specified and width. /// /// Gets the GDI+ native object. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal IntPtr NativePen { get { //Need to comment this line out to allow for checking this.NativePen == IntPtr.Zero. //Debug.Assert(this.nativePen != IntPtr.Zero, "this.nativePen == null." ); return this.nativePen; } } /** * Create a copy of the pen object */ ////// /// Creates an exact copy of this public object Clone() { IntPtr clonePen = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipClonePen(new HandleRef(this, this.NativePen), out clonePen); if (status != SafeNativeMethods.Gdip.Ok) { throw SafeNativeMethods.Gdip.StatusException(status); } return new Pen(clonePen); } /** * Dispose of resources associated with the Pen object */ ///. /// /// /// Cleans up Windows resources for this public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } void Dispose(bool disposing) { #if FINALIZATION_WATCH if (!disposing && nativePen != IntPtr.Zero) Debug.WriteLine("**********************\nDisposed through finalization:\n" + allocationSite); #endif if (!disposing) { // If we are finalizing, then we will be unreachable soon. Finalize calls dispose to // release resources, so we must make sure that during finalization we are // not immutable. // immutable = false; } else if (immutable) { throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Brush")); } if (this.nativePen != IntPtr.Zero) { try{ #if DEBUG int status = #endif SafeNativeMethods.Gdip.GdipDeletePen(new HandleRef(this, this.NativePen)); #if DEBUG Debug.Assert(status == SafeNativeMethods.Gdip.Ok, "GDI+ returned an error status: " + status.ToString(CultureInfo.InvariantCulture)); #endif } catch( Exception ex ){ if(ClientUtils.IsSecurityOrCriticalException( ex ) ) { throw; } Debug.Fail( "Exception thrown during Dispose: " + ex.ToString() ); } finally{ this.nativePen = IntPtr.Zero; } } } ///. /// /// /// Cleans up Windows resources for this ~Pen() { Dispose(false); } /** * Set/get pen width */ ///. /// /// /// Gets or sets the width of this public float Width { get { float[] width = new float[] { 0}; int status = SafeNativeMethods.Gdip.GdipGetPenWidth(new HandleRef(this, this.NativePen), width); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return width[0]; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenWidth(new HandleRef(this, this.NativePen), value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get line caps: start, end, and dash */ ///. /// /// /// public void SetLineCap(LineCap startCap, LineCap endCap, DashCap dashCap) { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenLineCap197819(new HandleRef(this, this.NativePen), (int)startCap, (int)endCap, (int)dashCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ////// Sets the values that determine the style of /// cap used to end lines drawn by this ///. /// /// /// public LineCap StartCap { get { int startCap = 0; int status = SafeNativeMethods.Gdip.GdipGetPenStartCap(new HandleRef(this, this.NativePen), out startCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(LineCap) startCap; } set { //validate the enum value switch(value) { case LineCap.Flat: case LineCap.Square: case LineCap.Round: case LineCap.Triangle: case LineCap.NoAnchor: case LineCap.SquareAnchor: case LineCap.RoundAnchor: case LineCap.DiamondAnchor: case LineCap.ArrowAnchor: case LineCap.AnchorMask: case LineCap.Custom: break; default: throw new InvalidEnumArgumentException("value", (int)value, typeof(LineCap)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenStartCap(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// Gets or sets the cap style used at the /// beginning of lines drawn with this ///. /// /// /// public LineCap EndCap { get { int endCap = 0; int status = SafeNativeMethods.Gdip.GdipGetPenEndCap(new HandleRef(this, this.NativePen), out endCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(LineCap) endCap; } set { //validate the enum value switch(value) { case LineCap.Flat: case LineCap.Square: case LineCap.Round: case LineCap.Triangle: case LineCap.NoAnchor: case LineCap.SquareAnchor: case LineCap.RoundAnchor: case LineCap.DiamondAnchor: case LineCap.ArrowAnchor: case LineCap.AnchorMask: case LineCap.Custom: break; default: throw new InvalidEnumArgumentException("value", (int)value, typeof(LineCap)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenEndCap(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// Gets or sets the cap style used at the end of /// lines drawn with this ///. /// /// /// Gets or sets the cap style used at the /// beginning or end of dashed lines drawn with this public DashCap DashCap { get { int dashCap = 0; int status = SafeNativeMethods.Gdip.GdipGetPenDashCap197819(new HandleRef(this, this.NativePen), out dashCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(DashCap)dashCap; } set { //validate the enum value if (!ClientUtils.IsEnumValid_NotSequential(value, (int)value, (int)DashCap.Flat, (int)DashCap.Round, (int)DashCap.Triangle)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(DashCap)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenDashCap197819(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get line join */ ///. /// /// /// Gets or sets the join style for the ends of /// two overlapping lines drawn with this public LineJoin LineJoin { get { int lineJoin = 0; int status = SafeNativeMethods.Gdip.GdipGetPenLineJoin(new HandleRef(this, this.NativePen), out lineJoin); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(LineJoin)lineJoin; } set { //valid values are 0x0 to 0x3 if (!ClientUtils.IsEnumValid(value, (int)value, (int)LineJoin.Miter, (int)LineJoin.MiterClipped)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(LineJoin)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenLineJoin(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get custom start line cap */ ///. /// /// /// public CustomLineCap CustomStartCap { get { IntPtr lineCap = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipGetPenCustomStartCap(new HandleRef(this, this.NativePen), out lineCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return CustomLineCap.CreateCustomLineCapObject(lineCap); } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenCustomStartCap(new HandleRef(this, this.NativePen), new HandleRef(value, (value == null) ? IntPtr.Zero : value.nativeCap)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get custom end line cap */ ////// Gets or sets a custom cap style to use at the beginning of lines /// drawn with this ///. /// /// /// public CustomLineCap CustomEndCap { get { IntPtr lineCap = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipGetPenCustomEndCap(new HandleRef(this, this.NativePen), out lineCap); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return CustomLineCap.CreateCustomLineCapObject(lineCap); } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenCustomEndCap(new HandleRef(this, this.NativePen), new HandleRef(value, (value == null) ? IntPtr.Zero : value.nativeCap)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// Gets or sets a custom cap style to use at the end of lines /// drawn with this ///. /// /// /// Gets or sets the limit of the thickness of /// the join on a mitered corner. /// public float MiterLimit { get { float[] miterLimit = new float[] { 0}; int status = SafeNativeMethods.Gdip.GdipGetPenMiterLimit(new HandleRef(this, this.NativePen), miterLimit); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return miterLimit[0]; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenMiterLimit(new HandleRef(this, this.NativePen), value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Pen Mode */ ////// /// public PenAlignment Alignment { get { PenAlignment penMode = 0; int status = SafeNativeMethods.Gdip.GdipGetPenMode(new HandleRef(this, this.NativePen), out penMode); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(PenAlignment) penMode; } set { //validate the enum value //valid values are 0x0 to 0x4 if (!ClientUtils.IsEnumValid(value, (int)value, (int)PenAlignment.Center, (int)PenAlignment.Right)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(PenAlignment)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenMode(new HandleRef(this, this.NativePen), value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } /** * Set/get pen transform */ ////// Gets or sets /// the alignment for objects drawn with this ///. /// /// /// public Matrix Transform { get { Matrix matrix = new Matrix(); int status = SafeNativeMethods.Gdip.GdipGetPenTransform(new HandleRef(this, this.NativePen), new HandleRef(matrix, matrix.nativeMatrix)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return matrix; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); if (value == null) { throw new ArgumentNullException("value"); } int status = SafeNativeMethods.Gdip.GdipSetPenTransform(new HandleRef(this, this.NativePen), new HandleRef(value, value.nativeMatrix)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// Gets /// or sets the geometrical transform for objects drawn with this ///. /// /// /// Resets the geometric transform for this /// public void ResetTransform() { int status = SafeNativeMethods.Gdip.GdipResetPenTransform(new HandleRef(this, this.NativePen)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ///to /// identity. /// /// /// public void MultiplyTransform(Matrix matrix) { MultiplyTransform(matrix, MatrixOrder.Prepend); } ////// Multiplies the transform matrix for this /// ///by /// the specified . /// /// /// public void MultiplyTransform(Matrix matrix, MatrixOrder order) { int status = SafeNativeMethods.Gdip.GdipMultiplyPenTransform(new HandleRef(this, this.NativePen), new HandleRef(matrix, matrix.nativeMatrix), order); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ////// Multiplies the transform matrix for this /// ///by /// the specified in the specified order. /// /// /// public void TranslateTransform(float dx, float dy) { TranslateTransform(dx, dy, MatrixOrder.Prepend); } ////// Translates the local geometrical transform /// by the specified dimmensions. This method prepends the translation to the /// transform. /// ////// /// Translates the local geometrical transform /// by the specified dimmensions in the specified order. /// public void TranslateTransform(float dx, float dy, MatrixOrder order) { int status = SafeNativeMethods.Gdip.GdipTranslatePenTransform(new HandleRef(this, this.NativePen), dx, dy, order); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ////// /// Scales the local geometric transform by the /// specified amounts. This method prepends the scaling matrix to the transform. /// public void ScaleTransform(float sx, float sy) { ScaleTransform(sx, sy, MatrixOrder.Prepend); } ////// /// public void ScaleTransform(float sx, float sy, MatrixOrder order) { int status = SafeNativeMethods.Gdip.GdipScalePenTransform(new HandleRef(this, this.NativePen), sx, sy, order); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } ////// Scales the local geometric transform by the /// specified amounts in the specified order. /// ////// /// Rotates the local geometric transform by the /// specified amount. This method prepends the rotation to the transform. /// public void RotateTransform(float angle) { RotateTransform(angle, MatrixOrder.Prepend); } ////// /// public void RotateTransform(float angle, MatrixOrder order) { int status = SafeNativeMethods.Gdip.GdipRotatePenTransform(new HandleRef(this, this.NativePen), angle, order); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } /** * Set/get pen type (color, line texture, or brush) * * @notes GetLineFill returns either a Brush object * or a LineTexture object. */ private void InternalSetColor(Color value) { int status = SafeNativeMethods.Gdip.GdipSetPenColor(new HandleRef(this, this.NativePen), color.ToArgb()); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); this.color = value; } ////// Rotates the local geometric transform by the specified /// amount in the specified order. /// ////// /// Gets the style of lines drawn with this /// public PenType PenType { get { int type = -1; int status = SafeNativeMethods.Gdip.GdipGetPenFillType(new HandleRef(this, this.NativePen), out type); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(PenType)type; } } ///. /// /// /// public Color Color { get { if (color == Color.Empty) { int colorARGB = 0; int status = SafeNativeMethods.Gdip.GdipGetPenColor(new HandleRef(this, this.NativePen), out colorARGB); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); this.color = Color.FromArgb(colorARGB); } // GDI+ doesn't understand system colors, so we can't use GdipGetPenColor in the general case return this.color; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); if( value != this.color ) { Color oldColor = this.color; this.color = value; InternalSetColor(value); // if (value.IsSystemColor && !oldColor.IsSystemColor) SystemColorTracker.Add(this); } } } ////// Gets or sets the color of this ///. /// /// /// Gets or sets the public Brush Brush { get { Brush brush = null; switch (PenType) { case PenType.SolidColor: brush = new SolidBrush(GetNativeBrush()); break; case PenType.HatchFill: brush = new HatchBrush(GetNativeBrush()); break; case PenType.TextureFill: brush = new TextureBrush(GetNativeBrush()); break; case PenType.PathGradient: brush = new PathGradientBrush(GetNativeBrush()); break; case PenType.LinearGradient: brush = new LinearGradientBrush(GetNativeBrush()); break; default: break; } return brush; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); if (value == null) throw new ArgumentNullException("value"); int status = SafeNativeMethods.Gdip.GdipSetPenBrushFill(new HandleRef(this, this.NativePen), new HandleRef(value, value.NativeBrush)); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } private IntPtr GetNativeBrush() { IntPtr nativeBrush = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipGetPenBrushFill(new HandleRef(this, this.NativePen), out nativeBrush); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return nativeBrush; } /** * Set/get dash attributes */ ///that /// determines attributes of this . /// /// /// Gets or sets the style used for dashed /// lines drawn with this public DashStyle DashStyle { get { int dashstyle = 0; int status = SafeNativeMethods.Gdip.GdipGetPenDashStyle(new HandleRef(this, this.NativePen), out dashstyle); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return(DashStyle) dashstyle; } set { //valid values are 0x0 to 0x5 if (!ClientUtils.IsEnumValid(value, (int)value, (int)DashStyle.Solid, (int)DashStyle.Custom)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(DashStyle)); } if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenDashStyle(new HandleRef(this, this.NativePen), (int)value); if (status != SafeNativeMethods.Gdip.Ok) { throw SafeNativeMethods.Gdip.StatusException(status); } //if we just set pen style to "custom" without defining the custom dash pattern, //lets make sure we can return a valid value... // if (value == DashStyle.Custom) { EnsureValidDashPattern(); } } } ///. /// /// /// This method is called after the user sets the pen's dash style to custom. /// Here, we make sure that there is a default value set for the custom pattern. /// private void EnsureValidDashPattern() { int retval = 0; int status = SafeNativeMethods.Gdip.GdipGetPenDashCount(new HandleRef(this, this.NativePen), out retval); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); if (retval == 0) { //just set to a solid pattern DashPattern = new float[]{1}; } } ////// /// Gets or sets the distance from the start of /// a line to the beginning of a dash pattern. /// public float DashOffset { get { float[] dashoffset = new float[] { 0}; int status = SafeNativeMethods.Gdip.GdipGetPenDashOffset(new HandleRef(this, this.NativePen), dashoffset); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return dashoffset[0]; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenDashOffset(new HandleRef(this, this.NativePen), value); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// /// public float[] DashPattern { get { float[] dashArray; // Figure out how many dash elements we have int retval = 0; int status = SafeNativeMethods.Gdip.GdipGetPenDashCount(new HandleRef(this, this.NativePen), out retval); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); int count = retval; // Allocate temporary native memory buffer // and pass it to GDI+ to retrieve dash array elements IntPtr buf = Marshal.AllocHGlobal(4 * count); status = SafeNativeMethods.Gdip.GdipGetPenDashArray(new HandleRef(this, this.NativePen), buf, count); try { if (status != SafeNativeMethods.Gdip.Ok) { throw SafeNativeMethods.Gdip.StatusException(status); } dashArray = new float[count]; Marshal.Copy(buf, dashArray, 0, count); } finally { Marshal.FreeHGlobal(buf); } return dashArray; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); //validate the DashPattern value being set if (value == null || value.Length == 0) { throw new ArgumentException(SR.GetString(SR.InvalidDashPattern)); } int count = value.Length; IntPtr buf = Marshal.AllocHGlobal(4 * count); try { Marshal.Copy(value, 0, buf, count); int status = SafeNativeMethods.Gdip.GdipSetPenDashArray(new HandleRef(this, this.NativePen), new HandleRef(buf, buf), count); if (status != SafeNativeMethods.Gdip.Ok){ throw SafeNativeMethods.Gdip.StatusException(status); } } finally { Marshal.FreeHGlobal(buf); } } } ////// Gets or sets an array of cutom dashes and /// spaces. The dashes are made up of line segments. /// ////// /// Gets or sets an array of cutom dashes and /// spaces. The dashes are made up of line segments. /// public float[] CompoundArray { get { int count = 0; int status = SafeNativeMethods.Gdip.GdipGetPenCompoundCount(new HandleRef(this, this.NativePen), out count); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); float[] array = new float[count]; status = SafeNativeMethods.Gdip.GdipGetPenCompoundArray(new HandleRef(this, this.NativePen), array, count); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); return array; } set { if (immutable) throw new ArgumentException(SR.GetString(SR.CantChangeImmutableObjects, "Pen")); int status = SafeNativeMethods.Gdip.GdipSetPenCompoundArray(new HandleRef(this, this.NativePen), value, value.Length); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); } } ////// void ISystemColorTracker.OnSystemColorChanged() { if (this.NativePen != IntPtr.Zero) InternalSetColor(color); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PartialClassGenerationTask.cs
- formatter.cs
- ThreadAbortException.cs
- ClickablePoint.cs
- _FtpControlStream.cs
- DBAsyncResult.cs
- SettingsPropertyCollection.cs
- UniqueIdentifierService.cs
- CapabilitiesPattern.cs
- ParameterToken.cs
- DesignerDataColumn.cs
- StreamUpgradeInitiator.cs
- HttpCacheVaryByContentEncodings.cs
- ModuleBuilderData.cs
- RegisteredHiddenField.cs
- LinqDataSourceView.cs
- ParserContext.cs
- FormatterConverter.cs
- EventHandlers.cs
- DiagnosticStrings.cs
- SigningProgress.cs
- SrgsToken.cs
- SeparatorAutomationPeer.cs
- DataContractSerializer.cs
- WindowsFormsEditorServiceHelper.cs
- ConfigXmlText.cs
- MenuItemBinding.cs
- FloaterBaseParagraph.cs
- TextRunCache.cs
- DataColumnPropertyDescriptor.cs
- IpcClientManager.cs
- SqlClientWrapperSmiStream.cs
- SvcMapFile.cs
- KeyProperty.cs
- XPathQilFactory.cs
- EndpointIdentityConverter.cs
- WhitespaceRule.cs
- RefType.cs
- TableLayout.cs
- ExpanderAutomationPeer.cs
- URLIdentityPermission.cs
- WindowsTab.cs
- ReverseComparer.cs
- NameObjectCollectionBase.cs
- NodeInfo.cs
- XmlObjectSerializerWriteContextComplex.cs
- BitArray.cs
- XmlMemberMapping.cs
- InputLangChangeRequestEvent.cs
- Track.cs
- WebEvents.cs
- MethodInfo.cs
- XhtmlCssHandler.cs
- BindingNavigator.cs
- StoragePropertyMapping.cs
- PropertyAccessVisitor.cs
- Literal.cs
- KeyGestureValueSerializer.cs
- _UriTypeConverter.cs
- CommunicationObject.cs
- BitmapSizeOptions.cs
- GridToolTip.cs
- ToolStripContainer.cs
- ChtmlTextWriter.cs
- ListViewItemSelectionChangedEvent.cs
- ServerIdentity.cs
- DbProviderManifest.cs
- FileAuthorizationModule.cs
- DataColumnMappingCollection.cs
- WindowsGraphicsWrapper.cs
- ReadOnlyAttribute.cs
- PageThemeBuildProvider.cs
- EditCommandColumn.cs
- TreeViewCancelEvent.cs
- TypedTableBase.cs
- Variant.cs
- PageContent.cs
- SocketInformation.cs
- DataRelation.cs
- odbcmetadatacollectionnames.cs
- PeerTransportListenAddressConverter.cs
- CopyNodeSetAction.cs
- Metafile.cs
- FixedTextSelectionProcessor.cs
- IsolatedStorage.cs
- BasicHttpMessageSecurityElement.cs
- DataGridViewImageCell.cs
- PeerCustomResolverElement.cs
- ConversionValidationRule.cs
- DataGridPageChangedEventArgs.cs
- XPathPatternBuilder.cs
- IndexedWhereQueryOperator.cs
- FloaterParagraph.cs
- DataDocumentXPathNavigator.cs
- ItemContainerPattern.cs
- VarRefManager.cs
- TypedOperationInfo.cs
- StreamWithDictionary.cs
- XmlCharacterData.cs
- CipherData.cs