//============================================================================
//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
//Copyright © 2004 John Champion
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//=============================================================================
#region Using directives
using System;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.IO;
#endregion
namespace DrawGraph
{
///
/// An abstract base class that defines basic functionality for handling a pane. This class is the
/// parent class for and .
///
///
/// John Champion
/// $Revision: 3.30 $ $Date: 2007/05/18 13:28:17 $
abstract public class PaneBase : ICloneable
{
#region Fields
///
/// The rectangle that defines the full area into which the pane is rendered. Units are pixels.
/// Use the public property to access this value.
///
protected RectangleF _rect;
/// Private field that holds the main title of the pane. Use the
/// public property to access this value.
///
protected GapLabel _title;
/// Private field instance of the class. Use the
/// public property to access this class.
protected Legend _legend;
///
/// Private field that stores the user-defined tag for this . This tag
/// can be any user-defined value. If it is a type, it can be used as
/// a parameter to the method. Use the public property
/// to access this value.
///
protected object _tag;
///
/// private field to store the margin values for this . Use the
/// public property to access this property.
///
internal Margin _margin;
/// Private field that determines whether or not the fonts, tics, gaps, etc.
/// will be scaled according to the actual graph size. true for font and feature scaling
/// with graph size, false for fixed font sizes (scaleFactor = 1.0 constant).
/// Use the public property to access this value.
///
///
protected bool _isFontsScaled;
///
/// Private field that controls whether or not pen widths are scaled according to the
/// size of the graph. This value is only applicable if
/// is true. If is false, then no scaling will be done,
/// regardless of the value of .
///
/// true to scale the pen widths according to the size of the graph,
/// false otherwise.
///
///
protected bool _isPenWidthScaled;
///
/// Private field that stores the data for the
/// background. Use the public property to
/// access this value.
///
protected Fill _fill;
///
/// Private field that stores the data for the
/// border. Use the public property to
/// access this value.
///
protected Border _border;
/// Private field instance of the class. Use the
/// public property to access this class.
protected GraphObjList _graphObjList;
/// Private field that determines the base size of the pane, in inches.
/// Fonts, tics, gaps, etc. are scaled according to this base size.
/// Use the public property to access this value.
///
///
protected float _baseDimension;
///
/// private field that stores the gap between the bottom of the pane title and the
/// client area of the pane. This is expressed as a fraction of the title character height.
///
protected float _titleGap;
#endregion
#region Defaults
///
/// A simple struct that defines the default property values for the class.
///
public struct Default
{
// Default GraphPane properties
///
/// The default display mode for the title at the top of the pane
/// ( property). true to
/// display a title, false otherwise.
///
public static bool IsShowTitle = true;
///
/// The default font family for the title
/// ( property).
///
public static string FontFamily = "Arial";
///
/// The default font size (points) for the
/// ( property).
///
public static float FontSize = 16;
///
/// The default font color for the
///
/// ( property).
///
public static Color FontColor = Color.Black;
///
/// The default font bold mode for the
///
/// ( property). true
/// for a bold typeface, false otherwise.
///
public static bool FontBold = true;
///
/// The default font italic mode for the
///
/// ( property). true
/// for an italic typeface, false otherwise.
///
public static bool FontItalic = false;
///
/// The default font underline mode for the
///
/// ( property). true
/// for an underlined typeface, false otherwise.
///
public static bool FontUnderline = false;
///
/// The default border mode for the .
/// ( property). true
/// to draw a border around the ,
/// false otherwise.
///
public static bool IsBorderVisible = true;
///
/// The default color for the border.
/// ( property).
///
public static Color BorderColor = Color.Black;
///
/// The default color for the background.
/// ( property).
///
public static Color FillColor = Color.White;
///
/// The default pen width for the border.
/// ( property). Units are in points (1/72 inch).
///
public static float BorderPenWidth = 1;
///
/// The default dimension of the , which
/// defines a normal sized plot. This dimension is used to scale the
/// fonts, symbols, etc. according to the actual size of the
/// .
///
///
public static float BaseDimension = 8.0F;
///
/// The default setting for the option.
/// true to have all pen widths scaled according to ,
/// false otherwise.
///
///
public static bool IsPenWidthScaled = false;
///
/// The default setting for the option.
/// true to have all fonts scaled according to ,
/// false otherwise.
///
///
public static bool IsFontsScaled = true;
///
/// The default value for the property, expressed as
/// a fraction of the scaled character height.
///
public static float TitleGap = 0.5f;
}
#endregion
#region Properties
///
/// The rectangle that defines the full area into which all graphics
/// will be rendered.
///
/// Note that this rectangle has x, y, width, and height. Most of the
/// GDI+ graphic primitive actually draw one pixel beyond those dimensions. For
/// example, for a rectangle of ( X=0, Y=0, Width=100, Height=100 ), GDI+ would
/// draw into pixels 0 through 100, which is actually 101 pixels. For the
/// ZedGraph Rect, a Width of 100 pixels means that pixels 0 through 99 are used
/// Units are pixels.
///
public RectangleF Rect
{
get { return _rect; }
set { _rect = value; }
}
///
/// Accesses the for this
///
/// A reference to a object
public Legend Legend
{
get { return _legend; }
}
///
/// Gets the instance that contains the text and attributes of the title.
/// This text can be multiple lines separated by newline characters ('\n').
///
///
///
///
///
///
///
///
public Label Title
{
get { return _title; }
}
///
/// Gets or sets the user-defined tag for this . This tag
/// can be any user-defined value. If it is a type, it can be used as
/// a parameter to the method.
///
///
/// Note that, if you are going to Serialize ZedGraph data, then any type
/// that you store in must be a serializable type (or
/// it will cause an exception).
///
public object Tag
{
get { return _tag; }
set { _tag = value; }
}
///
/// Gets or sets the class for drawing the border
/// border around the
///
///
///
public Border Border
{
get { return _border; }
set { _border = value; }
}
///
/// Gets or sets the data for the
/// filling the background of the .
///
public Fill Fill
{
get { return _fill; }
set { _fill = value; }
}
///
/// Gets or sets the list of items for this
///
/// A reference to a collection object
public GraphObjList GraphObjList
{
get { return _graphObjList; }
set { _graphObjList = value; }
}
///
/// Gets or sets the instance that controls the space between
/// the edge of the and the rendered content of the graph.
///
public Margin Margin
{
get { return _margin; }
set { _margin = value; }
}
///
/// BaseDimension is a double precision value that sets "normal" pane size on
/// which all the settings are based. The BaseDimension is in inches. For
/// example, if the BaseDimension is 8.0 inches and the
/// size is 14 points. Then the pane title font
/// will be 14 points high when the is approximately 8.0
/// inches wide. If the Rect is 4.0 inches wide, the pane title font will be
/// 7 points high. Most features of the graph are scaled in this manner.
///
/// The base dimension reference for the , in inches
///
///
///
public float BaseDimension
{
get { return _baseDimension; }
set { _baseDimension = value; }
}
///
/// Gets or sets the gap between the bottom of the pane title and the
/// client area of the pane. This is expressed as a fraction of the scaled
/// character height.
///
public float TitleGap
{
get { return _titleGap; }
set { _titleGap = value; }
}
///
/// Determines if the font sizes, tic sizes, gap sizes, etc. will be scaled according to
/// the size of the and the . If this
/// value is set to false, then the font sizes and tic sizes will always be exactly as
/// specified, without any scaling.
///
/// True to have the fonts and tics scaled, false to have them constant
///
public bool IsFontsScaled
{
get { return _isFontsScaled; }
set { _isFontsScaled = value; }
}
///
/// Gets or sets the property that controls whether or not pen widths are scaled for this
/// .
///
/// This value is only applicable if
/// is true. If is false, then no scaling will be done,
/// regardless of the value of . Note that scaling the pen
/// widths can cause "artifacts" to appear at typical screen resolutions. This occurs
/// because of roundoff differences; in some cases the pen width may round to 1 pixel wide
/// and in another it may round to 2 pixels wide. The result is typically undesirable.
/// Therefore, this option defaults to false. This option is primarily useful for high
/// resolution output, such as printer output or high resolution bitmaps (from
/// ) where it is desirable to have the pen width
/// be consistent with the screen image.
///
/// true to scale the pen widths according to the size of the graph,
/// false otherwise.
///
///
public bool IsPenWidthScaled
{
get { return _isPenWidthScaled; }
set { _isPenWidthScaled = value; }
}
#endregion
#region Constructors
///
/// Default constructor for the class. Leaves the empty.
///
public PaneBase() : this( "", new RectangleF( 0, 0, 0, 0 ) )
{
}
///
/// Default constructor for the class. Specifies the of
/// the , and the size of the .
///
public PaneBase( string title, RectangleF paneRect )
{
_rect = paneRect;
_legend = new Legend();
_baseDimension = Default.BaseDimension;
_margin = new Margin();
_titleGap = Default.TitleGap;
_isFontsScaled = Default.IsFontsScaled;
_isPenWidthScaled = Default.IsPenWidthScaled;
_fill = new Fill( Default.FillColor );
_border = new Border( Default.IsBorderVisible, Default.BorderColor,
Default.BorderPenWidth );
_title = new GapLabel( title, Default.FontFamily,
Default.FontSize, Default.FontColor, Default.FontBold,
Default.FontItalic, Default.FontUnderline );
_title._fontSpec.Fill.IsVisible = false;
_title._fontSpec.Border.IsVisible = false;
_graphObjList = new GraphObjList();
_tag = null;
}
///
/// The Copy Constructor
///
/// The object from which to copy
public PaneBase( PaneBase rhs )
{
// copy over all the value types
_isFontsScaled = rhs._isFontsScaled;
_isPenWidthScaled = rhs._isPenWidthScaled;
_titleGap = rhs._titleGap;
_baseDimension = rhs._baseDimension;
_margin = rhs._margin.Clone();
_rect = rhs._rect;
// Copy the reference types by cloning
_fill = rhs._fill.Clone();
_border = rhs._border.Clone();
_title = rhs._title.Clone();
_legend = rhs.Legend.Clone();
_title = rhs._title.Clone();
_graphObjList = rhs._graphObjList.Clone();
if ( rhs._tag is ICloneable )
_tag = ((ICloneable) rhs._tag).Clone();
else
_tag = rhs._tag;
}
//abstract public object ShallowClone();
///
/// Implement the interface in a typesafe manner by just
/// calling the typed version of Clone
///
///
/// Note that this method must be called with an explicit cast to ICloneable, and
/// that it is inherently virtual. For example:
///
/// ParentClass foo = new ChildClass();
/// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
///
/// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
/// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
/// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
///
/// A deep copy of this object
object ICloneable.Clone()
{
throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
//return new PaneBase( this );
}
///
/// Create a shallow, memberwise copy of this class.
///
///
/// Note that this method uses MemberWiseClone, which will copy all
/// members (shallow) including those of classes derived from this class.
/// a new copy of the class
public PaneBase ShallowClone()
{
// return a shallow copy
return this.MemberwiseClone() as PaneBase;
}
#endregion
#region Serialization
///
/// Current schema value that defines the version of the serialized file
///
// schema changed to 2 when Label Class added
public const int schema = 10;
///
/// Constructor for deserializing objects
///
/// A instance that defines the serialized data
///
/// A instance that contains the serialized data
///
protected PaneBase( SerializationInfo info, StreamingContext context )
{
// The schema value is just a file version parameter. You can use it to make future versions
// backwards compatible as new member variables are added to classes
int sch = info.GetInt32( "schema" );
_rect = (RectangleF) info.GetValue( "rect", typeof(RectangleF) );
_legend = (Legend) info.GetValue( "legend", typeof(Legend) );
_title = (GapLabel) info.GetValue( "title", typeof(GapLabel) );
//this.isShowTitle = info.GetBoolean( "isShowTitle" );
_isFontsScaled = info.GetBoolean( "isFontsScaled" );
_isPenWidthScaled = info.GetBoolean( "isPenWidthScaled" );
//this.fontSpec = (FontSpec) info.GetValue( "fontSpec" , typeof(FontSpec) );
_titleGap = info.GetSingle( "titleGap" );
_fill = (Fill) info.GetValue( "fill", typeof(Fill) );
_border = (Border) info.GetValue( "border", typeof(Border) );
_baseDimension = info.GetSingle( "baseDimension" );
_margin = (Margin)info.GetValue( "margin", typeof( Margin ) );
_graphObjList = (GraphObjList) info.GetValue( "graphObjList", typeof(GraphObjList) );
_tag = info.GetValue( "tag", typeof(object) );
}
///
/// Populates a instance with the data needed to serialize the target object
///
/// A instance that defines the serialized data
/// A instance that contains the serialized data
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
{
info.AddValue( "schema", schema );
info.AddValue( "rect", _rect );
info.AddValue( "legend", _legend );
info.AddValue( "title", _title );
//info.AddValue( "isShowTitle", isShowTitle );
info.AddValue( "isFontsScaled", _isFontsScaled );
info.AddValue( "isPenWidthScaled", _isPenWidthScaled );
info.AddValue( "titleGap", _titleGap );
//info.AddValue( "fontSpec", fontSpec );
info.AddValue( "fill", _fill );
info.AddValue( "border", _border );
info.AddValue( "baseDimension", _baseDimension );
info.AddValue( "margin", _margin );
info.AddValue( "graphObjList", _graphObjList );
info.AddValue( "tag", _tag );
}
#endregion
#region Methods
///
/// Do all rendering associated with this to the specified
/// device. This abstract method is implemented by the child
/// classes.
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
public virtual void Draw( Graphics g )
{
if ( _rect.Width <= 1 || _rect.Height <= 1 )
return;
// calculate scaleFactor on "normal" pane size (BaseDimension)
float scaleFactor = this.CalcScaleFactor();
// Fill the pane background and draw a border around it
DrawPaneFrame( g, scaleFactor );
// Clip everything to the rect
g.SetClip( _rect );
// Draw the GraphItems that are behind everything
_graphObjList.Draw( g, this, scaleFactor, ZOrder.H_BehindAll );
// Draw the Pane Title
DrawTitle( g, scaleFactor );
// Draw the Legend
//this.Legend.Draw( g, this, scaleFactor );
// Reset the clipping
g.ResetClip();
}
///
/// Calculate the client area rectangle based on the .
///
/// The client rectangle is the actual area available for
/// or items after taking out space for the margins and the title.
/// This method does not take out the area required for the .
/// To do so, you must separately call .
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
///
/// The scaling factor for the features of the graph based on the . This
/// scaling factor is calculated by the method. The scale factor
/// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
///
/// The calculated chart rect, in pixel coordinates.
public RectangleF CalcClientRect( Graphics g, float scaleFactor )
{
// get scaled values for the paneGap and character height
//float scaledOuterGap = (float) ( Default.OuterPaneGap * scaleFactor );
float charHeight = _title._fontSpec.GetHeight( scaleFactor );
// chart rect starts out at the full pane rect. It gets reduced to make room for the legend,
// scales, titles, etc.
RectangleF innerRect = new RectangleF(
_rect.Left + _margin.Left * scaleFactor,
_rect.Top + _margin.Top * scaleFactor,
_rect.Width - scaleFactor * ( _margin.Left + _margin.Right ),
_rect.Height - scaleFactor * ( _margin.Top + _margin.Bottom ) );
// Leave room for the title
if ( _title._isVisible && _title._text != string.Empty )
{
SizeF titleSize = _title._fontSpec.BoundingBox( g, _title._text, scaleFactor );
// Leave room for the title height, plus a line spacing of charHeight * _titleGap
innerRect.Y += titleSize.Height + charHeight * _titleGap;
innerRect.Height -= titleSize.Height + charHeight * _titleGap;
}
// Calculate the legend rect, and back it out of the current ChartRect
//this.legend.CalcRect( g, this, scaleFactor, ref innerRect );
return innerRect;
}
///
/// Draw the border _border around the area.
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
///
/// The scaling factor for the features of the graph based on the . This
/// scaling factor is calculated by the method. The scale factor
/// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
///
public void DrawPaneFrame( Graphics g, float scaleFactor )
{
// Erase the pane background, filling it with the specified brush
_fill.Draw( g, _rect );
// Reduce the rect width and height by 1 pixel so that for a rect of
// new RectangleF( 0, 0, 100, 100 ), which should be 100 pixels wide, we cover
// from 0 through 99. The draw routines normally cover from 0 through 100, which is
// actually 101 pixels wide.
RectangleF rect = new RectangleF( _rect.X, _rect.Y, _rect.Width - 1, _rect.Height - 1 );
_border.Draw( g, this, scaleFactor, rect );
}
///
/// Draw the on the graph, centered at the top of the pane.
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
///
/// The scaling factor for the features of the graph based on the . This
/// scaling factor is calculated by the method. The scale factor
/// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
///
public void DrawTitle( Graphics g, float scaleFactor )
{
// only draw the title if it's required
if ( _title._isVisible )
{
SizeF size = _title._fontSpec.BoundingBox( g, _title._text, scaleFactor );
// use the internal fontSpec class to draw the text using user-specified and/or
// default attributes.
_title._fontSpec.Draw( g, this, _title._text,
( _rect.Left + _rect.Right ) / 2,
_rect.Top + _margin.Top * (float) scaleFactor + size.Height / 2.0F,
AlignH.Center, AlignV.Center, scaleFactor );
}
}
///
/// Change the size of the . Override this method to handle resizing the contents
/// as required.
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
/// The new size for the .
public virtual void ReSize( Graphics g, RectangleF rect )
{
_rect = rect;
}
///
/// Calculate the scaling factor based on the ratio of the current dimensions and
/// the .
///
/// This scaling factor is used to proportionally scale the
/// features of the so that small graphs don't have huge fonts, and vice versa.
/// The scale factor represents a linear multiple to be applied to font sizes, symbol sizes, tic sizes,
/// gap sizes, pen widths, etc. The units of the scale factor are "World Pixels" per "Standard Point".
/// If any object size, in points, is multiplied by this scale factor, the result is the size, in pixels,
/// that the object should be drawn using the standard GDI+ drawing instructions. A "Standard Point"
/// is a dimension based on points (1/72nd inch) assuming that the size
/// matches the .
/// Note that "World Pixels" will still be transformed by the GDI+ transform matrices to result
/// in "Output Device Pixels", but "World Pixels" are the reference basis for the drawing commands.
///
///
/// A value representing the scaling factor to use for the rendering calculations.
///
///
public float CalcScaleFactor()
{
float scaleFactor; //, xInch, yInch;
const float ASPECTLIMIT = 1.5F;
// if font scaling is turned off, then always return a 1.0 scale factor
if ( !_isFontsScaled )
return 1.0f;
// Assume the standard width (BaseDimension) is 8.0 inches
// Therefore, if the rect is 8.0 inches wide, then the fonts will be scaled at 1.0
// if the rect is 4.0 inches wide, the fonts will be half-sized.
// if the rect is 16.0 inches wide, the fonts will be double-sized.
// Scale the size depending on the client area width in linear fashion
if ( _rect.Height <= 0 )
return 1.0F;
float length = _rect.Width;
float aspect = _rect.Width / _rect.Height;
if ( aspect > ASPECTLIMIT )
length = _rect.Height * ASPECTLIMIT;
if ( aspect < 1.0F / ASPECTLIMIT )
length = _rect.Width * ASPECTLIMIT;
scaleFactor = length / ( _baseDimension * 72F );
// Don't let the scaleFactor get ridiculous
if ( scaleFactor < 0.1F )
scaleFactor = 0.1F;
return scaleFactor;
}
///
/// Calculate the scaled pen width, taking into account the scaleFactor and the
/// setting of the property of the pane.
///
/// The pen width, in points (1/72 inch)
///
/// The scaling factor for the features of the graph based on the . This
/// scaling factor is calculated by the method. The scale factor
/// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
///
/// The scaled pen width, in world pixels
public float ScaledPenWidth( float penWidth, float scaleFactor )
{
if ( _isPenWidthScaled )
return (float)( penWidth * scaleFactor );
else
return penWidth;
}
///
/// Build a object containing the graphical rendering of
/// all the objects in this list.
///
/// A object rendered with the current graph.
///
///
///
public Bitmap GetImage()
{
Bitmap bitmap = new Bitmap( (int)_rect.Width, (int)_rect.Height );
using ( Graphics bitmapGraphics = Graphics.FromImage( bitmap ) )
{
bitmapGraphics.TranslateTransform( -_rect.Left, -_rect.Top );
this.Draw( bitmapGraphics );
}
return bitmap;
}
///
/// Gets an image for the current GraphPane, scaled to the specified size and resolution.
///
/// The scaled width of the bitmap in pixels
/// The scaled height of the bitmap in pixels
/// The resolution of the bitmap, in dots per inch
///
///
///
///
public Bitmap GetImage( int width, int height, float dpi )
{
Bitmap bitmap = new Bitmap( width, height );
bitmap.SetResolution( dpi, dpi );
using ( Graphics bitmapGraphics = Graphics.FromImage( bitmap ) )
{
MakeImage( bitmapGraphics, width, height );
}
return bitmap;
}
private void MakeImage( Graphics g, int width, int height )
{
//g.SmoothingMode = SmoothingMode.AntiAlias;
// This is actually a shallow clone, so we don't duplicate all the data, curveLists, etc.
PaneBase tempPane = this.ShallowClone();
// Clone the Chart object for GraphPanes so we don't mess up the minPix and maxPix values or
// the rect/ChartRect calculations of the original
//RectangleF saveRect = new RectangleF();
//if ( this is GraphPane )
// saveRect = ( this as GraphPane ).Chart.Rect;
tempPane.ReSize( g, new RectangleF( 0, 0, width, height ) );
tempPane.Draw( g );
//if ( this is GraphPane )
//{
// GraphPane gPane = this as GraphPane;
// gPane.Chart.Rect = saveRect;
// gPane.XAxis.Scale.SetupScaleData( gPane, gPane.XAxis );
// foreach ( Axis axis in gPane.YAxisList )
// axis.Scale.SetupScaleData( gPane, axis );
// foreach ( Axis axis in gPane.Y2AxisList )
// axis.Scale.SetupScaleData( gPane, axis );
//}
// To restore all the various state variables, you must redraw the graph in it's
// original form. For this we create a 1x1 bitmap (it doesn't matter what size you use,
// since we're only mimicing the draw. If you use the 'bitmapGraphics' already created,
// then you will be drawing back into the bitmap that will be returned.
Bitmap bm = new Bitmap( 1, 1 );
using ( Graphics bmg = Graphics.FromImage( bm ) )
{
this.ReSize( bmg, this.Rect );
this.Draw( bmg );
}
}
///
/// Gets an enhanced metafile image for the current GraphPane, scaled to the specified size.
///
///
/// By definition, a Metafile is a vector drawing, and therefore scaling should not matter.
/// However, this method is provided because certain options in Zedgraph, such as
/// are affected by the size of the expected image.
///
/// The "effective" scaled width of the bitmap in pixels
/// The "effective" scaled height of the bitmap in pixels
///
///
///
public Metafile GetMetafile( int width, int height )
{
Bitmap bm = new Bitmap( 1, 1 );
using ( Graphics g = Graphics.FromImage( bm ) )
{
IntPtr hdc = g.GetHdc();
Stream stream = new MemoryStream();
Metafile metafile = new Metafile( stream, hdc, _rect,
MetafileFrameUnit.Pixel, EmfType.EmfPlusDual );
g.ReleaseHdc( hdc );
using ( Graphics metafileGraphics = Graphics.FromImage( metafile ) )
{
//metafileGraphics.TranslateTransform( -_rect.Left, -_rect.Top );
metafileGraphics.PageUnit = System.Drawing.GraphicsUnit.Pixel;
PointF P = new PointF( width, height );
PointF[] PA = new PointF[] { P };
metafileGraphics.TransformPoints( CoordinateSpace.Page, CoordinateSpace.Device, PA );
//metafileGraphics.PageScale = 1f;
// output
MakeImage( metafileGraphics, width, height );
//this.Draw( metafileGraphics );
return metafile;
}
}
}
///
/// Gets an enhanced metafile image for the current GraphPane.
///
///
///
///
public Metafile GetMetafile()
{
Bitmap bm = new Bitmap( 1, 1 );
using ( Graphics g = Graphics.FromImage( bm ) )
{
IntPtr hdc = g.GetHdc();
Stream stream = new MemoryStream();
Metafile metafile = new Metafile( stream, hdc, _rect,
MetafileFrameUnit.Pixel, EmfType.EmfOnly );
using ( Graphics metafileGraphics = Graphics.FromImage( metafile ) )
{
metafileGraphics.TranslateTransform( -_rect.Left, -_rect.Top );
metafileGraphics.PageUnit = System.Drawing.GraphicsUnit.Pixel;
PointF P = new PointF( _rect.Width, _rect.Height );
PointF[] PA = new PointF[] { P };
metafileGraphics.TransformPoints( CoordinateSpace.Page, CoordinateSpace.Device, PA );
//metafileGraphics.PageScale = 1f;
// output
this.Draw( metafileGraphics );
g.ReleaseHdc( hdc );
return metafile;
}
}
}
/*
System.Drawing.Imaging.Metafile metafile = null;
// create a Metafile object that is compatible with the surface of this
// form
using ( Graphics graphics = this.CreateGraphics() )
{
System.IntPtr hdc = graphics.GetHdc();
metafile = new Metafile(filename, hdc, new Rectangle( 0, 0,
(((int) this.ClientRectangle.Width)),
(((int) this.ClientRectangle.Height ))),
MetafileFrameUnit.Point );
graphics.ReleaseHdc( hdc );
}
// draw to the metafile
using ( Graphics metafileGraphics = Graphics.FromImage( metafile ) )
{
metafileGraphics.PageUnit=System.Drawing.GraphicsUnit.Point;
PointF P=new Point(this.ClientRectangle.Width,this.ClientRectangle.Height);
PointF[] PA=new PointF[]{P};
metafileGraphics.TransformPoints(CoordinateSpace.Page, CoordinateSpace.Device, PA);
metafileGraphics.PageScale=1f;
metafileGraphics.SmoothingMode = SmoothingMode.AntiAlias; // smooth the
// output
this.masterPane.Draw( metafileGraphics );
metafileGraphics.DrawRectangle(new System.Drawing.Pen( Color.Gray),this.ClientRectangle);
metafile.Dispose();
}
return true;
}
else
{
return false;
}
}
else
{
//no directory given
return false;
}
*/
/*
///
/// Function to export the Diagram as WMF file
/// see http://www.codeproject.com/showcase/pdfrasterizer.asp?print=true
///
///
/// filename is the name to export to
///
public bool ExporttoWmf( string filename )
{
string p;
//FileInfo TheFile = new FileInfo(filename);
p = Path.GetDirectoryName( filename );
if ( p != "" )
{
DirectoryInfo TheDir = new DirectoryInfo( p );
if ( TheDir.Exists )
{
System.Drawing.Imaging.Metafile metafile = null;
// create a Metafile object that is compatible with the surface of this
// form
using ( Graphics graphics = this.CreateGraphics() )
{
System.IntPtr hdc = graphics.GetHdc();
metafile = new Metafile( filename, hdc, new Rectangle( 0, 0,
( ( (int)this.ClientRectangle.Width ) ),
( ( (int)this.ClientRectangle.Height ) ) ),
MetafileFrameUnit.Point );
graphics.ReleaseHdc( hdc );
}
// draw to the metafile
using ( Graphics metafileGraphics = Graphics.FromImage( metafile ) )
{
metafileGraphics.PageUnit = System.Drawing.GraphicsUnit.Point;
PointF P = new Point( this.ClientRectangle.Width, this.ClientRectangle.Height );
PointF[] PA = new PointF[] { P };
metafileGraphics.TransformPoints( CoordinateSpace.Page, CoordinateSpace.Device, PA );
metafileGraphics.PageScale = 1f;
metafileGraphics.SmoothingMode = SmoothingMode.AntiAlias; // smooth the
// output
this.masterPane.Draw( metafileGraphics );
metafileGraphics.DrawRectangle( new System.Drawing.Pen( Color.Gray ), this.ClientRectangle );
metafile.Dispose();
}
return true;
}
else
{
return false;
}
}
else
{
//no directory given
return false;
}
}
*/
internal PointF TransformCoord( double x, double y, CoordType coord )
{
// If the Transformation is an illegal type, just stick it in the middle
if ( !( this is GraphPane ) && !( coord == CoordType.PaneFraction ) )
{
coord = CoordType.PaneFraction;
x = 0.5;
y = 0.5;
}
// Just to save some casts
GraphPane gPane = null;
RectangleF chartRect = new RectangleF( 0, 0, 1, 1 );
if ( this is GraphPane )
{
gPane = this as GraphPane;
chartRect = gPane.Chart._rect;
}
PointF ptPix = new PointF();
if ( coord == CoordType.ChartFraction )
{
ptPix.X = (float)( chartRect.Left + x * chartRect.Width );
ptPix.Y = (float)( chartRect.Top + y * chartRect.Height );
}
else if ( coord == CoordType.AxisXYScale )
{
ptPix.X = gPane.XAxis.Scale.Transform( x );
ptPix.Y = gPane.YAxis.Scale.Transform( y );
}
else if ( coord == CoordType.AxisXY2Scale )
{
ptPix.X = gPane.XAxis.Scale.Transform( x );
ptPix.Y = gPane.Y2Axis.Scale.Transform( y );
}
else if ( coord == CoordType.XScaleYChartFraction )
{
ptPix.X = gPane.XAxis.Scale.Transform( x );
ptPix.Y = (float)( chartRect.Top + y * chartRect.Height );
}
else if ( coord == CoordType.XChartFractionYScale )
{
ptPix.X = (float)( chartRect.Left + x * chartRect.Width );
ptPix.Y = gPane.YAxis.Scale.Transform( y );
}
else if ( coord == CoordType.XChartFractionY2Scale )
{
ptPix.X = (float)( chartRect.Left + x * chartRect.Width );
ptPix.Y = gPane.Y2Axis.Scale.Transform( y );
}
else if ( coord == CoordType.XChartFractionYPaneFraction )
{
ptPix.X = (float)( chartRect.Left + x * chartRect.Width );
ptPix.Y = (float)( this.Rect.Top + y * _rect.Height );
}
else if ( coord == CoordType.XPaneFractionYChartFraction )
{
ptPix.X = (float)( this.Rect.Left + x * _rect.Width );
ptPix.Y = (float)( chartRect.Top + y * chartRect.Height );
}
else // PaneFraction
{
ptPix.X = (float)( _rect.Left + x * _rect.Width );
ptPix.Y = (float)( _rect.Top + y * _rect.Height );
}
return ptPix;
}
#endregion
}
}