Pen.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / CommonUI / System / Drawing / Pen.cs / 1 / Pen.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/*************************************************************************\ 
* 
* Copyright (c) 1998-1999, Microsoft Corp.  All Rights Reserved.
* 
* Module Name:
*
*   Pen.cs
* 
* Abstract:
* 
*   COM+ wrapper for GDI+ path objects 
*
* Revision History: 
*
*   01/11/1999 davidx
*       Code review changes.
* 
*   12/15/1998 [....]
*       Created it. 
* 
\**************************************************************************/
 
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;
 
    /// 
    ///  
    ///      
    ///         Defines an object used to draw lines and curves.
    ///      
    /// 
    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;
 
        /// 
        ///     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;
        } 
 
        /// 
        ///  
        ///    
        ///       Initializes a new instance of the Pen
        ///       class with the specified .
        ///     
        /// 
        public Pen(Color color) : this(color, (float)1.0) { 
        } 

        ///  
        /// 
        ///    
        ///       Initializes a new instance of the   class with the specified
        ///        and . 
        /// 
        ///  
        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 Pen class with the
        ///       specified .
        ///     
        /// 
        public Pen(Brush brush) : this(brush, (float)1.0) { 
        } 

        ///  
        /// 
        ///    
        ///       Initializes a new instance of the  class with
        ///       the specified  and width. 
        ///    
        ///  
        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;
        }
 
        /// 
        ///    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
         */
        ///  
        /// 
        ///     
        ///       Sets the values that determine the style of 
        ///       cap used to end lines drawn by this .
        ///     
        /// 
        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);
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets the cap style used at the
        ///       beginning of lines drawn with 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 end 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 
        ///    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
         */ 
        /// 
        /// 
        ///    
        ///       Gets or sets a custom cap style to use at the beginning of lines 
        ///       drawn with this .
        ///     
        ///  
        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 end 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 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
         */ 
        ///  
        /// 
        ///     
        ///       Gets or sets
        ///       the alignment for objects drawn with this .
        ///    
        ///  
        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 geometrical transform 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); 
            } 
        }
 
        /// 
        /// 
        ///    Resets the geometric transform for this
        ///  to 
        ///    identity.
        ///  
        public void ResetTransform() { 
            int status = SafeNativeMethods.Gdip.GdipResetPenTransform(new HandleRef(this, this.NativePen));
 
            if (status != SafeNativeMethods.Gdip.Ok)
                throw SafeNativeMethods.Gdip.StatusException(status);
        }
 
        /// 
        ///  
        ///     
        ///       Multiplies the transform matrix for this
        ///     by 
        ///       the specified .
        ///    
        /// 
        public void MultiplyTransform(Matrix matrix) { 
            MultiplyTransform(matrix, MatrixOrder.Prepend);
        } 
 
        /// 
        ///  
        ///    
        ///       Multiplies the transform matrix for this
        ///     by
        ///       the specified  in the specified order. 
        ///    
        ///  
        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); 
        }
 
        ///  
        /// 
        ///     
        ///       Translates the local geometrical transform
        ///       by the specified dimmensions. This method prepends the translation to the
        ///       transform.
        ///     
        /// 
        public void TranslateTransform(float dx, float dy) { 
            TranslateTransform(dx, dy, MatrixOrder.Prepend); 
        }
 
        /// 
        /// 
        ///    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);
        }
 
        /// 
        ///  
        ///     
        ///       Scales the local geometric transform by the
        ///       specified amounts in the specified order. 
        ///    
        /// 
        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);
        } 

        /// 
        /// 
        ///    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);
        } 

        /// 
        /// 
        ///     
        ///       Rotates the local geometric transform by the specified
        ///       amount in the specified order. 
        ///     
        /// 
        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;
        } 

        ///  
        ///  
        ///    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;
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Gets or sets the color of this .
        ///    
        /// 
        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  that 
        ///    determines attributes of this .
        ///  
        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 
         */
        ///  
        ///  
        ///    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);
            }
        } 

        ///  
        ///  
        ///    
        ///       Gets or sets an array of cutom dashes and 
        ///       spaces. The dashes are made up of line segments.
        ///    
        /// 
        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.
        /// 
        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.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK