Changes

Jump to: navigation, search

Drawing Graphics using PowerShell 1.0 and GDI+

9,931 bytes added, 19:59, 18 December 2008
New page: Windows PowerShell leverages the GDI+ library to provide graphics drawing capabilities. In fact, PowerShell provides the same level of drawing capabilities through GDI+ as those available ...
Windows PowerShell leverages the GDI+ library to provide graphics drawing capabilities. In fact, PowerShell provides the same level of drawing capabilities through GDI+ as those available in other programming languages such as C# and Visual Basic. In fact, those familiar with GDI+ in the context of other programming languages will find the learning curve to be extremely shallow. Those with no previous experience of GDI+ graphics drawing will quickly find that it is both intuitive and easy to learn.

== An Overview of GDI+ ==

GDI+ is part of the .NET framwork and is the standard Windows API for working with display hardware to draw graphics on Windows XP, Windows Server 2003 and later Microsoft operating systems. The ''GDI'' in ''GDI+'' is an abbreviation for ''Graphics Display Interface''. In terms of using GDI+ within Windows PowerShell it is used in conjunction with WinForms, whereby WinForms provides dialogs, controls and the Form canvas on which the drawing takes place. For more information in WinForms in the context of Windows PowerShell, refer to the chapter entitled [[Creating GUIs in Windows PowerShell 1.0 with WinForms]].

== Loading the GDI+ and WinForms .NET Assemblies ==

As previously mention, Windows PowerShell GDI+ development is typically performed in conjunction with WinForms. Neither the GDI+, nor the WinForms .NET assemblies are loaded into the Windows PowerShell environment by default. It is necessary, therefore, to load these assemblies before beginning the development process. GDI+ and Winforms reside in the [Windows.Drawing] and [Windows.Windows.Forms] assemblies respectively. These can be loaded using the following commands:

<pre>
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
[reflection.assembly]::LoadWithPartialName( "System.Drawing")
</pre>

== Creating Drawing Objects ==

Once the appropriate .NET assemblies are loaded, the next step is to create objects with which to draw graphics. The example in this chapter will focus on the Pen and SolidBrush objects. GDI+ provides a range of other drawing objects, details of which are covered in the MSDN .NET documentation.

The following example creates SolidBrush and Pen objects which will be used later in this chapter to perform drawing operations:

<pre>
$myBrush = new-object Drawing.SolidBrush green
$mypen = new-object Drawing.Pen black
</pre>

== Setting Properties of a GDI+ Drawing Object ==

Just as with any other object, each GDI+ drawing object contains a set of methods and properties which are accessible from within Windows PowerShell. A full list of available methods and properties of an object may be obtained using the ''get-member'' cmdlet. For example,the following command lists all the methods and properties of the $mypen object created in the previous section:

<pre>
PS C:\tmp> $pen | get-member


TypeName: System.Drawing.Pen

Name MemberType Definition
---- ---------- ----------
Clone Method System.Object Clone()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedT...
Dispose Method System.Void Dispose()

.
.
.

Alignment Property System.Drawing.Drawing2D.PenAlignment Alignment {get;set;}
Brush Property System.Drawing.Brush Brush {get;set;}
Color Property System.Drawing.Color Color {get;set;}
CompoundArray Property System.Single[] CompoundArray {get;set;}
CustomEndCap Property System.Drawing.Drawing2D.CustomLineCap CustomEndCap {get;set;}
CustomStartCap Property System.Drawing.Drawing2D.CustomLineCap CustomStartCap {get;...
DashCap Property System.Drawing.Drawing2D.DashCap DashCap {get;set;}
DashOffset Property System.Single DashOffset {get;set;}
DashPattern Property System.Single[] DashPattern {get;set;}
DashStyle Property System.Drawing.Drawing2D.DashStyle DashStyle {get;set;}
EndCap Property System.Drawing.Drawing2D.LineCap EndCap {get;set;}
LineJoin Property System.Drawing.Drawing2D.LineJoin LineJoin {get;set;}
MiterLimit Property System.Single MiterLimit {get;set;}
PenType Property System.Drawing.Drawing2D.PenType PenType {get;}
StartCap Property System.Drawing.Drawing2D.LineCap StartCap {get;set;}
Transform Property System.Drawing.Drawing2D.Matrix Transform {get;set;}
Width Property System.Single Width {get;set;}
</pre>

With knowledge of these methods and properties, it is possible to change characteristics of an object. For example, the color and width properties of the ''$mypen'' object may be modified as follows:

<pre>
$mypen.color = "red"
$mypen.width = 10
</pre>

== Creating the WinForm Form ==

Having defined the GDI+ drawing objects, the next step is to create a canvas on which to draw. For the purposes of this example, a Winforms ''Form'' will act as the drawing canvas. To create this form it is necessary to make use of the WinForms API:

<pre>
$form = New-Object Windows.Forms.Form
</pre>

Once the Form has been created, the next step is to create a graphics object on which to draw using the ''createGraphics()'' method of the Form object:

</pre>
$formGraphics = $form.createGraphics()
</pre>

== The Paint Event Handler ==

Applications with graphical user interfaces are primarily ''event driven''. This means that event handlers must be written to define what actions are to be performed when certain activities occur with regard to the user interface. When a user clicks a button, for example, an event handler performs the necessary tasks associated with that button being pressed (if the button was a Close button, the event handler would be responsible for exiting the application).

In terms of graphics drawing, when a form is displayed a ''paint'' event is triggered. Similarly, when a form needs to be repainted (for example because all or part of the form was obscured and then uncovered by another window), the paint event is also triggered. it is, therefore, the job of the ''paint handler'' to perform the graphics drawing tasks. A paint event handler is declared in Windows PowerShell via a call to ''add_paint()'':

<pre>
$form.add_paint(
{
# code or call to a function to perform graphics drawing
}
)


== Drawing Graphics with Windows PowerShell and GDI+ ==

As outlined in the preceding section, the code to draw the graphics is contained in the paint event handler. In this section we will look at some basic drawing methods.

The following example draws a line from the point at co-ordinates x=10, y=10 to the point at x=190, y=190. It does so using the previously created $myPen object.

<pre>
$formGraphics.DrawLine($pen, 10, 10, 190, 190)
</pre>

A filled ellipse is drawn by calling the ''FillEllipse()'' method of the graphics object, passing through a suitable drawing object (e.g a brush or a pen) and defining a rectangle into which the ellipse is to fit:

<pre>
$formGraphics.FillEllipse($myBrush, 20, 20, 180, 180)
</pre>

[[Image:windows_powershell_gdi_ellipse.jpg|A filled ellipse drawn using Windows PowerShell and GDI+]]

Similarly, a filed rectangle can be drawn using the ''FillRectange()'' method, once again passing through a pen or brush and defining the rectangle:

<pre>
$formGraphics.FillRectangle($myBrush, 0,0,200,200)
</pre>

[[Image:windows_powershell_gdi_filled_rectangle.jpg|A filled rectangle drawn using Windows PowerShell and GDI+]]

In the above example, rectangles were defined by passing co-ordinates directly through as arguments to the drawing methods. It is also possible to create Rectangle objects:

<pre>
$rect = new-object Drawing.Rectangle 0, 0, 200, 200

$formGraphics.FillRectangle($myBrush, $rect)
</pre>

No graphics drawing tutorial would be complete without a single bezier spline, and this chapter is no exception. The following example defines the start, end and two control points of a bezier spline and passes them through, along with a pen object, to the ''DrawBezier()'' method of the graphics object:

<pre>
$p1 = new-object Drawing.Point 10, 100
$p2 = new-object Drawing.Point 100, 10
$p3 = new-object Drawing.Point 170, 170
$p4 = new-object Drawing.Point 200, 100
</pre>

The above script will result in the following:

[[Image:windows_powershell_gdi_bezier.jpg|A Bezier spine drawn using Windows PowerShell and GDI+]]

== Bringing it All Together ==

Now that we have covered the basic requirements for displaying graphics using Windows PowerShell and GDI+ it is time to bring it all together in a working example. The following script, when executed, will draw a filled green circle and two red lines:

<pre>
#Load the GDI+ and WinForms Assemblies
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
[reflection.assembly]::LoadWithPartialName( "System.Drawing")

# Create pen and brush objects
$myBrush = new-object Drawing.SolidBrush green
$mypen = new-object Drawing.Pen black

# Create a Rectangle object for use when drawing rectangle
$rect = new-object Drawing.Rectangle 10, 10, 180, 180

# Create a Form
$form = New-Object Windows.Forms.Form

# Get the form's graphics object
$formGraphics = $form.createGraphics()


# Define the paint handler
$form.add_paint(
{

$formGraphics.FillEllipse($myBrush, $rect) # draw an ellipse using rectangle object

$mypen.color = "red" # Set the pen color
$mypen.width = 5 # ste the pen line width

$formGraphics.DrawLine($mypen, 10, 10, 190, 190) # draw a line

$formGraphics.DrawLine($mypen, 190, 10, 10, 190) # draw a line

}
)

$form.ShowDialog() # display the dialog
</pre>

When run, the resulting dialog will appear as follows:

[[Image:windows_powershell_gdi_example.jpg|A Windows PowerShell/GDI+ Example]]

[[Image:

Navigation menu