PowerTools SPREAD for Windows Forms 10.0J > SPREADデザイナガイド > シェイプの設計 > 高度な処理 > カスタム複合シェイプの作成 |
すべてのシェイプクラスには、1つのシェイプ内に別のシェイプを埋め込むことができるという独自の機能があります。これは、複合シェイプを作成するための優れた機能です。ここでは、次の図のような、複数の組み込みシェイプの組み合わせでウォーターマークのように機能する、カスタム複合シェイプの作成方法について説明します。
上図のカスタム複合シェイプを作成するには、CompanyWatermark という名前のカスタムシェイプクラスを定義し、各プロパティを設定して外観をカスタマイズします。このカスタムシェイプは、いくつかの要素を組み合わせて作成しています。背景色を特定の色から透明にグラデーション表示し、埋め込みシェイプによって企業ロゴイメージを表示し、独立した埋め込みテキストシェイプによって企業名を表示し、さらに追加情報(Web サイトアドレス、企業方針、セキュリティ分類など)を表示するテキストシェイプを表示しています。
ここではまず、標準のRectangleShapeクラスからクラスを派生させます。これは、さまざまな埋め込みシェイプを配置するための、長方形の土台となります。楕円、多角形など、他の任意のシェイプを簡単に使用できます。ただし、埋め込むシェイプは親シェイプの境界を越えて表示されないため、境界を越えた部分の埋め込みシェイプは切り取られます。
次に、埋め込むシェイプにアクセスするためのプロパティを作成します。複合シェイプを作成することの利点の1つは、埋め込みシェイプの多数の不要なプロパティを非表示にできることです。カスタムプロパティを使用することで、必要な情報だけを公開できます。最初に作成するのは「CompanyColor」プロパティです。これは背景グラデーションの主要な色であり、主要シェイプ内で、特定の色から透明へと段階的に薄く表示されます。また、背後のシートが完全に隠れないように、アルファブレンドを行います。グラデーションクラスを使用すると、グラデーションの方向と種類を定義するStyleなど、他のプロパティも設定できます。この例では、GradientStyle.TopDownというStyle値を使用しています。
次に作成するのは、「CompanyLogo」という名前のイメージプロパティです。 このプロパティは、埋め込んだロゴシェイプ内に表示するイメージを設定します。 この例では、ウォーターマークの左上隅にロゴシェイプをロックします。ロゴの配置を設定する各プロパティを使用することで、この機能を簡単に拡張できます。
ウォーターマークの最も重要な要素は、企業名です。これには、埋め込んだTextShapeオブジェクトを使用して、企業名を表します。これは、文字列の値を取る「CompanyName」プロパティによって、ウォーターマークシェイプ上に表示します。ここでは使用しませんが、TextShapeクラスにはこの他にもFontやForeColorなど、カスタマイズと公開が可能な多数の機能があります。また、サンプルを単純化するため、ウォーターマークシェイプの中央に企業名シェイプをロックします。
最後に、ウォーターマーク内に追加情報を表示するための、2番目のTextShapeオブジェクトを設定します。 追加情報には、企業方針、スローガン、Webサイトのアドレス、あるいは「CONFIDENTIAL」、「Copyright 2005」といったテキストを使用できます。ここでは、追加情報テキストをウォーターマークシェイプの左下隅に固定します。 この埋め込みシェイプには、他にも多数のプロパティを設定できます。 この例では、必要な項目だけを公開します。 このシェイプのテキストは、「CompanyText」プロパティによって公開します。
SPREADではビューポート ペインをスクロールできます。したがって、SPREADの TopChange および LeftChange イベントを上書きして、現在のシートに合わせてウォーターマークを移動させることで、ウォーターマークを常にスプレッドシートコントロール幅で、画面の最上部に表示できます。ウォーターマーク クラスの Top および Left プロパティも上書きし、各埋め込みオブジェクトを、ウォーターマーク内で常に表示されるように移動します。 |
次のサンプルコードは、上図で示したカスタム複合シェイプを作成するCompanyWatermarkクラスの使用方法、および実装方法を示しています。
以下、CompanyWatermarkクラスを使用してシートに複合シェイプを追加する方法です。
C# |
コードのコピー
|
---|---|
private void Form1_Load(object sender, EventArgs e) { CompanyWatermark test = new CompanyWatermark(0, 0, 550, 200); fpSpread1_Sheet1.AddShape(test); } |
Visual Basic |
コードのコピー
|
---|---|
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim test As New CompanyWatermark(0, 0, 550, 200) FpSpread1_Sheet1.AddShape(test) End Sub |
以下、CompanyWatermarkクラスの実装方法です。
C# |
コードのコピー
|
---|---|
using System; using System.Drawing; using System.Runtime.Serialization; using FarPoint.Win; using FarPoint.Win.Spread.DrawingSpace; using System.Xml; public class CompanyWatermark : RectangleShape, ISerializable { private Color mCompanyColor = Color.Green; private Image mCompanyLogo = WatermarkShape.Properties.Resources.SampleLogo; private string mCompanyName = "[Company Name]"; private string mCompanyText = "[Company Text]"; internal CompanyWatermark() { } // required for ISerializeSupport public CompanyWatermark(int left, int top, int width, int height) : base() { CanRotate = false; SetBounds(left, top, width, height); UpdateChildren(); } public CompanyWatermark(SerializationInfo info, StreamingContext context) : base(info, context) { mCompanyColor = (Color)info.GetValue("cc", typeof(Color)); mCompanyLogo = (Image)info.GetValue("cl", typeof(Image)); mCompanyName = info.GetString("cn"); mCompanyText = info.GetString("ct"); UpdateChildren(); } public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("cc", mCompanyColor); info.AddValue("cl", mCompanyLogo); info.AddValue("cn", mCompanyName); info.AddValue("ct", mCompanyText); } public Color CompanyColor { get { return mCompanyColor; } set { mCompanyColor = value; UpdateChildren(); } } public Image CompanyLogo { get { return mCompanyLogo; } set { mCompanyLogo = value; UpdateChildren(); } } public string CompanyName { get { return mCompanyName; } set { mCompanyName = value; UpdateChildren(); } } public string CompanyText { get { return mCompanyText; } set { mCompanyText = value; UpdateChildren(); } } public override void Rotate(float angle) { base.Rotate(angle); foreach (PSShape shape in ContainedObjects) shape.RotationAngle = angle; } public override bool Deserialize(XmlNodeReader r) { bool inCompanyColor = false; bool inCompanyLogo = false; XmlDocument doc = new XmlDocument(); XmlNode node; XmlNodeReader r2; XmlNodeReader r3; XmlNodeReader r4; r.MoveToElement(); node = doc.ReadNode(r); r2 = new XmlNodeReader(node); r3 = new XmlNodeReader(node); r4 = new XmlNodeReader(node); PSObject.Deserialize(this, r2); PSShape.Deserialize(this, r3); while (r4.Read()) { switch (r.NodeType) { case XmlNodeType.Element: if (r.Name.Equals("CompanyColor")) inCompanyColor = true; else if (r.Name.Equals("CompanyLogo")) inCompanyLogo = true; else if (r.Name.Equals("CompanyName")) mCompanyName = Serializer.DeserializeString(r); else if (r.Name.Equals("CompanyText")) mCompanyText = Serializer.DeserializeString(r); break; case XmlNodeType.Text: if (inCompanyColor) mCompanyColor = Serializer.DeserializeColorValue(r.Value); else if (inCompanyLogo) mCompanyLogo = Serializer.DeserializeImage(r.Value); break; case XmlNodeType.EndElement: if (inCompanyColor && r.Name.Equals("CompanyColor")) inCompanyColor = false; else if (inCompanyLogo && r.Name.Equals("CompanyLogo")) inCompanyLogo = false; break; } } return true; } public override bool Serialize(XmlTextWriter w) { w.WriteStartElement("PSShape"); w.WriteAttributeString("class", this.GetType().FullName); w.WriteAttributeString("assembly", this.GetType().Assembly.FullName); PSShape.Serialize(this, w); Serializer.SerializeColor(mCompanyColor, "CompanyColor", w); Serializer.SerializeImage(mCompanyLogo, "CompanyLogo", w); Serializer.SerializeString(mCompanyName, "CompanyName", w); Serializer.SerializeString(mCompanyText, "CompanyText", w); w.WriteEndElement(); // object return true; } private void UpdateChildren() { ShapeOutlineThickness = 0; if( ContainedObjects.Count == 0 ) { // create the child shapes // gradient effect for company color BackColor = Color.Transparent; Gradient.Sections = new GradientSection[] { new GradientSection(mCompanyColor, 255, 200), new GradientSection(Color.White, 255, 255) }; Gradient.Style = GradientStyle.LinearTopDown; // company logo is aligned to left and uses image width and height to align company text below RectangleShape logo = new RectangleShape(); logo.BackColor = Color.Transparent; logo.ShapeOutlineThickness = 0; logo.SetBounds(0, 0, mCompanyLogo.Width, mCompanyLogo.Height); logo.Picture = mCompanyLogo; logo.PictureTransparencyColor = Color.White; ContainedObjects.Add(logo); TextShape name = new TextShape(); name.Text = mCompanyName; name.ForeColor = Color.Orange; name.ShapeOutlineColor = Color.Black; name.ShapeOutlineStyle = System.Drawing.Drawing2D.DashStyle.Solid; name.ShapeOutlineThickness = 1; ContainedObjects.Add(name); name.SetBounds(logo.Width + 5, (logo.Height - name.Height) / 2, name.Width, name.Height); TextShape text = new TextShape(); text.Text = mCompanyText; text.ForeColor = Color.Red; text.ShapeOutlineColor = Color.Black; text.ShapeOutlineStyle = System.Drawing.Drawing2D.DashStyle.Solid; text.ShapeOutlineThickness = 1; ContainedObjects.Add(text); text.SetBounds(0, logo.Height + 5, text.Width, text.Height); } else { // update the child shapes RectangleShape logo = (RectangleShape)ContainedObjects[0]; TextShape name = (TextShape)ContainedObjects[1]; TextShape text = (TextShape)ContainedObjects[2]; Gradient.Sections = new GradientSection[] { new GradientSection(mCompanyColor, 50), new GradientSection(Color.White, 50) }; logo.Picture = mCompanyLogo; name.Text = mCompanyName; text.Text = mCompanyText; } } } |
Visual Basic |
コードのコピー
|
---|---|
Imports System.Runtime.Serialization Imports System.Xml Imports FarPoint.Win Imports FarPoint.Win.Spread.DrawingSpace <Serializable()> Public Class CompanyWatermark Inherits RectangleShape Implements ISerializable Private mCompanyColor As Color = Color.Green Private mCompanyLogo As Image = My.Resources.SampleLogo Private mCompanyName As String = "[Company Name]" Private mCompanyText As String = "[Company Text]" Friend Sub New() End Sub ' required for ISerializeSupport Public Sub New(left As Integer, top As Integer, width As Integer, height As Integer) MyBase.New() CanRotate = False SetBounds(left, top, width, height) UpdateChildren() End Sub Public Sub New(info As SerializationInfo, context As StreamingContext) MyBase.New(info, context) mCompanyColor = DirectCast(info.GetValue("cc", GetType(Color)), Color) mCompanyLogo = DirectCast(info.GetValue("cl", GetType(Image)), Image) mCompanyName = info.GetString("cn") mCompanyText = info.GetString("ct") UpdateChildren() End Sub Public Overrides Sub GetObjectData(info As SerializationInfo, context As StreamingContext) MyBase.GetObjectData(info, context) info.AddValue("cc", mCompanyColor) info.AddValue("cl", mCompanyLogo) info.AddValue("cn", mCompanyName) info.AddValue("ct", mCompanyText) End Sub Public Property CompanyColor() As Color Get Return mCompanyColor End Get Set mCompanyColor = Value UpdateChildren() End Set End Property Public Property CompanyLogo() As Image Get Return mCompanyLogo End Get Set mCompanyLogo = Value UpdateChildren() End Set End Property Public Property CompanyName() As String Get Return mCompanyName End Get Set mCompanyName = Value UpdateChildren() End Set End Property Public Property CompanyText() As String Get Return mCompanyText End Get Set mCompanyText = Value UpdateChildren() End Set End Property Public Overrides Sub Rotate(angle As Single) MyBase.Rotate(angle) For Each shape As PSShape In ContainedObjects shape.RotationAngle = angle Next End Sub Public Overrides Function Deserialize(r As XmlNodeReader) As Boolean Dim inCompanyColor As Boolean = False Dim inCompanyLogo As Boolean = False Dim doc As New XmlDocument() Dim node As XmlNode Dim r2 As XmlNodeReader Dim r3 As XmlNodeReader Dim r4 As XmlNodeReader r.MoveToElement() node = doc.ReadNode(r) r2 = New XmlNodeReader(node) r3 = New XmlNodeReader(node) r4 = New XmlNodeReader(node) PSObject.Deserialize(Me, r2) PSShape.Deserialize(Me, r3) While r4.Read() Select Case r.NodeType Case XmlNodeType.Element If r.Name.Equals("CompanyColor") Then inCompanyColor = True ElseIf r.Name.Equals("CompanyLogo") Then inCompanyLogo = True ElseIf r.Name.Equals("CompanyName") Then mCompanyName = Serializer.DeserializeString(r) ElseIf r.Name.Equals("CompanyText") Then mCompanyText = Serializer.DeserializeString(r) End If Exit Select Case XmlNodeType.Text If inCompanyColor Then mCompanyColor = Serializer.DeserializeColorValue(r.Value) ElseIf inCompanyLogo Then mCompanyLogo = Serializer.DeserializeImage(r.Value) End If Exit Select Case XmlNodeType.EndElement If inCompanyColor AndAlso r.Name.Equals("CompanyColor") Then inCompanyColor = False ElseIf inCompanyLogo AndAlso r.Name.Equals("CompanyLogo") Then inCompanyLogo = False End If Exit Select End Select End While Return True End Function Public Overrides Function Serialize(w As XmlTextWriter) As Boolean w.WriteStartElement("PSShape") w.WriteAttributeString("class", Me.[GetType]().FullName) w.WriteAttributeString("assembly", Me.[GetType]().Assembly.FullName) PSShape.Serialize(Me, w) Serializer.SerializeColor(mCompanyColor, "CompanyColor", w) Serializer.SerializeImage(mCompanyLogo, "CompanyLogo", w) Serializer.SerializeString(mCompanyName, "CompanyName", w) Serializer.SerializeString(mCompanyText, "CompanyText", w) w.WriteEndElement() ' object Return True End Function Private Sub UpdateChildren() ShapeOutlineThickness = 0 If ContainedObjects.Count = 0 Then ' create the child shapes ' gradient effect for company color BackColor = Color.Transparent Gradient.Sections = New GradientSection() {New GradientSection(mCompanyColor, 255, 200), New GradientSection(Color.White, 255, 255)} Gradient.Style = GradientStyle.LinearTopDown ' company logo is aligned to left and uses image width and height to align company text below Dim logo As New RectangleShape() logo.BackColor = Color.Transparent logo.ShapeOutlineThickness = 0 logo.SetBounds(0, 0, mCompanyLogo.Width, mCompanyLogo.Height) logo.Picture = mCompanyLogo logo.PictureTransparencyColor = Color.White ContainedObjects.Add(logo) Dim name As New TextShape() name.Text = mCompanyName name.ForeColor = Color.Orange name.ShapeOutlineColor = Color.Black name.ShapeOutlineStyle = System.Drawing.Drawing2D.DashStyle.Solid name.ShapeOutlineThickness = 1 ContainedObjects.Add(name) name.SetBounds(logo.Width + 5, (logo.Height - name.Height) / 2, name.Width, name.Height) Dim text As New TextShape() text.Text = mCompanyText text.ForeColor = Color.Red text.ShapeOutlineColor = Color.Black text.ShapeOutlineStyle = System.Drawing.Drawing2D.DashStyle.Solid text.ShapeOutlineThickness = 1 ContainedObjects.Add(text) text.SetBounds(0, logo.Height + 5, text.Width, text.Height) Else ' update the child shapes Dim logo As RectangleShape = DirectCast(ContainedObjects(0), RectangleShape) Dim name As TextShape = DirectCast(ContainedObjects(1), TextShape) Dim text As TextShape = DirectCast(ContainedObjects(2), TextShape) Gradient.Sections = New GradientSection() {New GradientSection(mCompanyColor, 50), New GradientSection(Color.White, 50)} logo.Picture = mCompanyLogo name.Text = mCompanyName text.Text = mCompanyText End If End Sub End Class |