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;
///
///
///
/// 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.
//
//-----------------------------------------------------------------------------
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.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DeviceContext.cs
- PackageRelationship.cs
- XmlAttributeProperties.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- ProgressPage.cs
- CopyOnWriteList.cs
- StandardBindingReliableSessionElement.cs
- MSHTMLHostUtil.cs
- COM2IVsPerPropertyBrowsingHandler.cs
- XmlEnumAttribute.cs
- XhtmlTextWriter.cs
- SqlVisitor.cs
- Normalizer.cs
- ProviderConnectionPointCollection.cs
- CustomExpressionEventArgs.cs
- GridViewRowPresenterBase.cs
- ChangeTracker.cs
- CacheDependency.cs
- ContourSegment.cs
- XmlDocumentSchema.cs
- ObjectManager.cs
- ModelUIElement3D.cs
- ToolStripItemRenderEventArgs.cs
- CaseInsensitiveOrdinalStringComparer.cs
- StylusPointPropertyInfo.cs
- WsdlParser.cs
- StylusPointCollection.cs
- XmlStreamStore.cs
- DispatchWrapper.cs
- SamlAction.cs
- _Connection.cs
- RegexStringValidatorAttribute.cs
- ChtmlTextWriter.cs
- Privilege.cs
- StoryFragments.cs
- ScrollBar.cs
- VariantWrapper.cs
- PrincipalPermission.cs
- UnsafeNativeMethods.cs
- _ListenerResponseStream.cs
- ISAPIWorkerRequest.cs
- IImplicitResourceProvider.cs
- ResourceContainer.cs
- AdRotatorDesigner.cs
- CLSCompliantAttribute.cs
- ActivityXRefPropertyEditor.cs
- DoubleLinkList.cs
- SqlProcedureAttribute.cs
- ConfigurationConverterBase.cs
- EventDescriptorCollection.cs
- x509store.cs
- CapabilitiesRule.cs
- _ProxyChain.cs
- ParameterToken.cs
- StringReader.cs
- CalendarDesigner.cs
- PasswordTextNavigator.cs
- WebPartTracker.cs
- DCSafeHandle.cs
- ToolboxSnapDragDropEventArgs.cs
- SecurityTokenSpecification.cs
- MediaTimeline.cs
- IteratorFilter.cs
- Exceptions.cs
- SqlDataSourceQueryEditorForm.cs
- MD5Cng.cs
- Visual3D.cs
- DetailsViewRow.cs
- processwaithandle.cs
- HashCryptoHandle.cs
- CacheVirtualItemsEvent.cs
- GroupPartitionExpr.cs
- QilTypeChecker.cs
- SrgsToken.cs
- SpellerInterop.cs
- XmlQueryOutput.cs
- WsdlHelpGeneratorElement.cs
- Comparer.cs
- OracleFactory.cs
- XmlSchemaDocumentation.cs
- PropertyRecord.cs
- QueryOptionExpression.cs
- XhtmlBasicLabelAdapter.cs
- FolderLevelBuildProviderAppliesToAttribute.cs
- BaseCodePageEncoding.cs
- AssemblyBuilderData.cs
- ClientBuildManagerTypeDescriptionProviderBridge.cs
- AnimationException.cs
- HandledEventArgs.cs
- SqlXmlStorage.cs
- HelpEvent.cs
- DebugController.cs
- XPathDocumentIterator.cs
- Point3DIndependentAnimationStorage.cs
- OpCodes.cs
- DataMisalignedException.cs
- DataServiceContext.cs
- ToggleButtonAutomationPeer.cs
- BlobPersonalizationState.cs
- RegistryPermission.cs