Listing 6-11 shows how to draw a Circle bitmap programmatically on the panel surface.. When an application needs to draw different shapes on the same panel surface, it just needs to dyna
Trang 1193
const PixelFormat PIXELFORMAT = PixelFormat.Format24bppRgb;
protected Bitmap bitmap = null;
protected Random random = null;
protected Graphics graphics = null;
protected int shapeWidth = 0;
protected int shapeHeight = 0;
protected int drawAreaWidth = 0;
protected int drawAreaHeight = 0;
public Shape(Panel drawArea)
{
if (null == drawArea
|| drawArea.Width <= 0
|| drawArea.Height <= 0)
{
throw new ArgumentException(
"The draw area must be specified and valid", drawArea.ToString());
}
random = new Random((int)DateTime.Now.Ticks);
bitmap = new Bitmap(drawArea.ClientRectangle.Width,
drawArea.ClientRectangle.Height,
PIXELFORMAT);
graphics = Graphics.FromImage( bitmap);
drawAreaWidth = drawArea.Width;
public Bitmap Map
{
get { return bitmap; }
}
public int ShapeWidth
{
get { return shapeWidth; }
}
public int ShapeHeight
{
get { return shapeHeight; }
}
protected int RandomWidth
{
get
{
shapeWidth = random.Next(0, drawAreaWidth);
return shapeWidth;
}
}
Trang 2194
protected int RandomHeight
{
get
{
shapeHeight = random.Next(0, drawAreaHeight);
return shapeHeight;
}
}
protected Pen RandomColorPen
{
get
{
return new Pen(Color.FromArgb( random.Next(0, 255),
random.Next(0, 255),
random.Next(0, 255)));
}
}
#endregion
#region Protected Method
protected void Reset()
{
if (null != bitmap)
{
Graphics.FromImage(this bitmap).Clear(Color.Black);
}
}
#endregion
abstract public void Draw();
}
}
A class derived from this base class is responsible for drawing a specific shape Listing 6-11 shows how to draw a Circle bitmap programmatically on the panel surface A protected function, Reset(),
is called before drawing This function clears the previously drawn bitmap and sets the bitmap to the background color When an application needs to draw different shapes on the same panel surface,
it just needs to dynamically construct a drawing class and pass in the panel object instance The implementation will be presented later in this exercise
Listing 6-11 Derived Drawing Class Used to Draw a Circle Bitmap on a Panel Surface
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
Trang 3195
namespace SoftnetSolutions.Shape
{
public class Circle : Shape, IShape
{
public Circle(Panel drawArea) : base(drawArea)
{
}
override public void Draw()
{
int width = base RandomWidth;
int height = base RandomHeight;
int radius = width / 2;
base Reset();
base graphics.DrawEllipse( base RandomColorPen,
width - radius,//convert to bounding rectangle
height - radius,//convert to bounding rectangle
radius,
radius);
}
}
}
SoftnetSolutions.RelayService.ServiceContract
The WCF service contract stays the same as the one we defined in the last exercise except for adding an operation contract, as Listing 6-12 shows
Listing 6-12 Adding an Operation Contact OnShapeSelecChanged to the Service Contract
IPublishEventService
using System;
using System.ServiceModel;
namespace SoftnetSolutions.RelayService.ServiceContract
{
[ServiceContract(Name = "IPublishEventService",
Namespace = "http://SoftnetSolutions.RelayService/")]
public interface IPublishEventService
{
[OperationContract(IsOneWay = true)]
void PostMessage(PostData postData);
[OperationContract(IsOneWay = true)]
void OnShapeSelectChanged(PostData shapeData);
}
Trang 4196
public interface IPublishEventServiceChannel : IPublishEventService, IClientChannel { } }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Reflection;
namespace SoftnetSolutions.RelayService.ServiceContract
{
using SoftnetSolutions.Shape;
[DataContract]
public class PostData : IComparable
{
[DataMember]
public string Message;
[DataMember]
public SHAPE TYPE shape { get; set; }
public int CompareTo(object obj)
{
if (obj is PostData)
{
PostData temp = (PostData)obj;
return shape.CompareTo(temp.shape);
}
throw new ArgumentException(
string.Format("object is not a <{0}> type", this.GetType().Name));
}
}
}
SoftnetSolutions.Shape.Draw
SoftnetSolutions.Shape.Draw is a Windows application that has two responsibilities:
1 Listen to the event published by the ShapeController and update the UI This
is done by implementing the WCF service contract IPublishEventService as the class declaration shows in Listing 6-13
Trang 5197
Listing 6-13 The FormDrawShape Implements the WCF Service Contract IPublishEventService
[ServiceBehavior(Name = "PublishEventService",
Namespace = "http://SoftnetSolutions.RelayService/",
InstanceContextMode = InstanceContextMode.Single)]
public partial class FormDrawShape : Form, IPublishEventService
{
}
2 Draw a shape according to the selected shape type This is done by using a factory
method design pattern in conjunction with a reflection class to dynamically load a
drawing object into memory as shown in Listing 6-14 Bitmap drawing is done by
implementing the drawPanel Paint() method and associating the bitmap to the
background image of the drawing panel as shown in Listing 6-15
Listing 6-14 Use Factory Method Design Pattern and Reflection Class to Dynamically Create a Shape
Object as a Type of IShape
private IShape ClassFactory()
{
string assemblyName = "SoftnetSolutions.Shape";
string className = string.Format("{0}.{1}",
assemblyName,
SHAPE NAME[(int)this shapeType]);
Assembly assembly = Assembly.Load(assemblyName);
Type classType = assembly.GetType(className);
IShape shapeClass =
(IShape)Activator.CreateInstance(
classType, new object[] {this.drawingPanel});
return shapeClass;
}
Listing 6-15 Implement the drawingPanel Paint Method to Associate the Bitmap Instance to the
Background Image of the Drawing Panel
private void drawingPanel Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
if (null == shape)
{
return;
}
drawingPanel.BackgroundImage = this shape.Map;
}