Implementing User Defined Objects With LEADTOOLS Annotations (Deprecated)

Implementing User-Defined Objects With LEADTOOLS Annotations (Deprecated)

Summary

You can easily create your own annotation objects with LEADTOOLS Annotations framework. This secion shows you how to create two new annotations objects and how to write the required designer for them to plug these objects into the LEADTOOLS Annotations Automation framework:

  1. Start by creating a new Windows Application project.
  2. Add references to the following DLL's:
    • Leadtools.dll
    • Leadtools.WinForms.dll
    • Leadtools.Codecs.dll
    • Leadtools.Annotations.dll
  3. The first object we are going to create is a simple triangle object. This object will have three points for the end points of the triangle and it will support a pen to stroke the triangle edges and a brush to fill the interior.

    Add a new class to your project, name this class MyTriangleObject. Following is the source code for this class:

    C#
    VB
    Imports System 
    Imports System.Drawing 
    Imports System.Drawing.Drawing2D 
    Imports System.Runtime.Serialization 
    Imports Leadtools.Annotations 
    ' 
    ' Triangle annotation object class 
    ' This class will have a 3 points for a triangle objects that can be stroked with a pen and filled with a brush 
    ' 
    ' our class must be serializable to play well with the annotation load/save and undo/redo features 
    <Serializable()> _ 
    Public Class MyTriangleObject 
       Inherits AnnObject    ' must derive from AnnObject or one of its derived classes 
       ' 
       ' our private variables 
       ' 
       ' the three points that define our triangle 
       <NonSerialized()> Private _firstPoint As AnnPoint 
       <NonSerialized()> Private _secondPoint As AnnPoint 
       <NonSerialized()> Private _thirdPoint As AnnPoint 
       ' 
       ' constructor 
       ' 
       Public Sub New() 
          ' supportsPen = yes, supportsBrush = yes, supportsFont = no 
          MyBase.New( _ 
             True, _ 
             True, _ 
             False) 
          ' initialize the points 
          _firstPoint = AnnPoint.Empty 
          _secondPoint = AnnPoint.Empty 
          _thirdPoint = AnnPoint.Empty 
       End Sub 
       ' 
       ' ISerializable implementation 
       ' 
       Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext) 
          MyBase.New(info, context)    ' do not forget to call the base class version 
          ' we need to deserialize our private variables here 
          _firstPoint = DirectCast(info.GetValue("FirstPointName", GetType(AnnPoint)), AnnPoint) 
          _secondPoint = DirectCast(info.GetValue("SecondPointName", GetType(AnnPoint)), AnnPoint) 
          _thirdPoint = DirectCast(info.GetValue("ThirdPointName", GetType(AnnPoint)), AnnPoint) 
       End Sub 
       Public Overrides Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) 
          ' we need to serialize our private variables here 
          ' call the base class version 
          MyBase.GetObjectData(info, context) 
          ' serialize the points 
          info.AddValue("FirstPointName", _firstPoint, GetType(AnnPoint)) 
          info.AddValue("SecondPointName", _secondPoint, GetType(AnnPoint)) 
          info.AddValue("ThirdPointName", _thirdPoint, GetType(AnnPoint)) 
       End Sub 
       ' 
       ' accessors to the points 
       ' 
       Public Property FirstPoint() As AnnPoint 
          Get 
             Return _firstPoint 
          End Get 
          Set(ByVal Value As AnnPoint) 
             _firstPoint = Value 
          End Set 
       End Property 
       Public Property SecondPoint() As AnnPoint 
          Get 
             Return _secondPoint 
          End Get 
          Set(ByVal Value As AnnPoint) 
             _secondPoint = Value 
          End Set 
       End Property 
       Public Property ThirdPoint() As AnnPoint 
          Get 
             Return _thirdPoint 
          End Get 
             Set(ByVal Value As AnnPoint) 
             _thirdPoint = Value 
          End Set 
       End Property 
       ' 
       ' AnnObject overrides 
       ' 
       Protected Overrides Function Create() As AnnObject 
          ' must return a new instance of our class 
          Return New MyTriangleObject 
       End Function 
       Public Overrides Function Clone() As Object 
          ' override the clone method 
          ' first call the base implementation 
          Dim obj As MyTriangleObject = DirectCast(MyBase.Clone(), MyTriangleObject) 
          ' next, copy the points 
          obj.FirstPoint = FirstPoint 
          obj.SecondPoint = SecondPoint 
          obj.ThirdPoint = ThirdPoint 
          Return obj 
       End Function 
       Public Overrides Function GetGraphicsPath(ByVal mode As AnnGetGraphicsPathMode) As GraphicsPath 
          ' must a return a graphics path representation of our object 
          ' Note: this object does not require us to override AnnObject.DrawObject since we can 
          ' use a graphics path to represents the object completely. 
          ' create a new graphics path 
          Dim path As New GraphicsPath 
          ' add the triangle points as a series of lines 
          ' convert the points to pixels PointF 
          Dim pts() As PointF = _ 
          { _ 
             FirstPoint.ConvertTo(UnitConverter, AnnUnit.Pixel).ToPointF(), _ 
             SecondPoint.ConvertTo(UnitConverter, AnnUnit.Pixel).ToPointF(), _ 
             ThirdPoint.ConvertTo(UnitConverter, AnnUnit.Pixel).ToPointF() _ 
          } 
          path.AddLines(pts) 
          path.CloseFigure() 
          Return path 
       End Function 
    End Class 
    using System; 
    using System.Drawing; 
    using System.Drawing.Drawing2D; 
    using System.Runtime.Serialization; 
    using Leadtools.Annotations; 
    namespace MyNamespace 
    { 
       // 
       // Triangle annotation object class 
       // This class will have a 3 points for a triangle objects that can be stroked with a pen and filled with a brush 
       // 
       [Serializable] // our class must be serializable to play well with the annotation load/save and undo/redo features 
       public class MyTriangleObject: 
          AnnObject    // must derive from AnnObject or one of its derived classes 
       { 
          // 
          // our private variables 
          // 
          // the three points that define our triangle 
          [NonSerialized()] private AnnPoint _firstPoint; 
          [NonSerialized()] private AnnPoint _secondPoint; 
          [NonSerialized()] private AnnPoint _thirdPoint; 
          // 
          // constructor 
          // 
          public MyTriangleObject() : 
             base( 
             true,    // yes, we require a pen 
             true,    // yes, we require a brush 
             false)    // no, we do not require a font 
          { 
             // initialize the points 
             _firstPoint = AnnPoint.Empty; 
             _secondPoint = AnnPoint.Empty; 
             _thirdPoint = AnnPoint.Empty; 
          } 
          // 
          // ISerializable implementation 
          // 
          protected MyTriangleObject(SerializationInfo info, StreamingContext context) : 
             base(info, context)    // do not forget to call the base class version 
          { 
             // we need to deserialize our private variables here 
             _firstPoint = (AnnPoint)info.GetValue("FirstPointName", typeof(AnnPoint)); 
             _secondPoint = (AnnPoint)info.GetValue("SecondPointName", typeof(AnnPoint)); 
             _thirdPoint = (AnnPoint)info.GetValue("ThirdPointName", typeof(AnnPoint)); 
          } 
          public override void GetObjectData(SerializationInfo info, StreamingContext context) 
          { 
             // we need to serialize our private variables here 
             // call the base class version 
             base.GetObjectData(info, context); 
             // serialize the points 
             info.AddValue("FirstPointName", _firstPoint, typeof(AnnPoint)); 
             info.AddValue("SecondPointName", _secondPoint, typeof(AnnPoint)); 
             info.AddValue("ThirdPointName", _thirdPoint, typeof(AnnPoint)); 
          } 
          // 
          // accessors to the points 
          // 
          public AnnPoint FirstPoint 
          { 
             get 
             { 
                return _firstPoint; 
             } 
             set 
             { 
                _firstPoint = value; 
             } 
          } 
          public AnnPoint SecondPoint 
          { 
             get 
             { 
                return _secondPoint; 
             } 
             set 
             { 
                _secondPoint = value; 
             } 
          } 
          public AnnPoint ThirdPoint 
          { 
             get 
             { 
                return _thirdPoint; 
             } 
             set 
             { 
                _thirdPoint = value; 
             } 
          } 
          // 
          // AnnObject overrides 
          // 
          protected override AnnObject Create() 
          { 
             // must return a new instance of our class 
             return new MyTriangleObject(); 
          } 
          public override object Clone() 
          { 
             // override the clone method 
             // first call the base implementation 
             MyTriangleObject obj = base.Clone() as MyTriangleObject; 
             // next, copy the points 
             obj.FirstPoint = FirstPoint; 
             obj.SecondPoint = SecondPoint; 
             obj.ThirdPoint = ThirdPoint; 
             return obj; 
          } 
          public override GraphicsPath GetGraphicsPath(AnnGetGraphicsPathMode mode) 
          { 
             // must a return a graphics path representation of our object 
             // Note: this object does not require us to override AnnObject.DrawObject since we can 
             // use a graphics path to represent the object completely. 
             // create a new graphics path 
             GraphicsPath path = new GraphicsPath(); 
             // add the triangle points as a series of lines 
             // convert the points to pixels PointF 
             PointF[] pts = 
             { 
                FirstPoint.ConvertTo(UnitConverter, AnnUnit.Pixel).ToPointF(), 
                SecondPoint.ConvertTo(UnitConverter, AnnUnit.Pixel).ToPointF(), 
                ThirdPoint.ConvertTo(UnitConverter, AnnUnit.Pixel).ToPointF() 
             }; 
          path.AddLines(pts); 
          path.CloseFigure(); 
          return path; 
          } 
       } 
    } 

    This enough to manually add, remove, load, save and draw this object to an annotation container. However, we want to be able to draw and edit this object using the annotation designers. Since we cannot find a suitable draw and edit designer to use with this class, we need to create our own.

  4. First, the draw designer, add a new class to your project, name this class "MyTriangleObjectDrawDesigner" and add the following code:

    C#
    VB
    Imports System 
    Imports System.Drawing 
    Imports System.Windows.Forms 
    Imports Leadtools.Annotations 
    ' 
    ' MyTriangleObject draw designer 
    ' Will require the user to click 3 times once for each point 
    ' 
    Public Class MyTriangleObjectDrawDesigner 
       Inherits AnnDrawDesigner    ' must derive from AnnDrawDesigner or one of its derived classes 
       ' 
       ' private variables 
       ' 
       ' we need to keep track on next point to add 
       Private _clickCount As Integer 
       ' 
       ' constructor 
       ' 
       Public Sub New() 
          _clickCount = 0 
       End Sub 
       ' 
       ' AnnDrawDesigner overrides 
       ' 
       Public Overrides Function MouseDown(ByVal e As MouseEventArgs) As Boolean 
          Dim handled As Boolean = False 
          ' only process left button clicks 
          If (e.Button = MouseButtons.Left) Then 
             ' check if we have not started drawing yet, DrawObject will be null 
             If (IsNothing(DrawObject)) Then 
                ' yes, create a new MyTriangleObject from ObjectTemplate 
                Dim obj As MyTriangleObject = DirectCast(ObjectTemplate.Clone(), MyTriangleObject) 
                ' setup the points 
                Dim pt As AnnPoint = GetLogicalAnnPoint(e.X, e.Y, obj.FirstPoint.Unit) 
                obj.FirstPoint = pt 
                obj.SecondPoint = pt 
                obj.ThirdPoint = pt 
                ' start drawing this new object 
                StartWorking(obj) 
                handled = True 
                ' we processed first click 
                _clickCount = _clickCount + 1 
             Else 
                ' an object is already being drawn, so process next click 
                ' get our object and assign next point to it 
                Dim obj As MyTriangleObject = DirectCast(DrawObject, MyTriangleObject) 
                Dim pt As AnnPoint = GetLogicalAnnPoint(e.X, e.Y, obj.FirstPoint.Unit) 
                If (_clickCount = 1) Then 
                   ' second point 
                   obj.SecondPoint = pt 
                   _clickCount = _clickCount + 1 
                ElseIf (_clickCount = 2) Then 
                   ' third point 
                   obj.ThirdPoint = pt 
                   ' we are done! 
                   EndWorking() 
                End If 
             End If 
          Else 
             ' we want to cancel the drawing if any other button has been clicked 
             If (Not IsNothing(DrawObject)) Then 
                Cancel() 
                handled = True 
             End If 
          End If 
          Return handled 
       End Function 
       Public Overrides Function MouseMove(ByVal e As MouseEventArgs) As Boolean 
          Dim handled As Boolean = False 
          ' check if we are already drawing an object 
          If (Not IsNothing(DrawObject)) Then 
             ' yes, get this object and assign the next point 
             ' first, save the old invalid rectangle 
             Dim rcOld As Rectangle = DrawObject.InvalidRectangle 
             ' get out object and assign the point 
             Dim obj As MyTriangleObject = DirectCast(DrawObject, MyTriangleObject) 
             Dim pt As AnnPoint = GetLogicalAnnPoint(e.X, e.Y, obj.FirstPoint.Unit) 
             If (_clickCount = 1) Then 
                obj.SecondPoint = pt 
             ElseIf (_clickCount = 2) Then 
                obj.ThirdPoint = pt 
             End If 
             ' get the new invalid rectangle 
             Dim rcNew As Rectangle = DrawObject.InvalidRectangle 
             ' continue drawing this object 
             Working(Rectangle.Union(rcOld, rcNew)) 
             handled = True 
          End If 
          Return handled 
       End Function 
       Public Overrides Function MouseUp(ByVal e As MouseEventArgs) As Boolean 
          ' we do not need to do anything special on mouse up. 
          ' so just see if we are drawing to return true (we handled it) 
          Dim handled As Boolean = False 
          If (IsNothing(DrawObject)) Then 
             handled = True 
          End If 
          Return handled 
       End Function 
    End Class 
    using System; 
    using System.Drawing; 
    using System.Windows.Forms; 
    using Leadtools.Annotations; 
    namespace MyNamespace 
    { 
       // 
       // MyTriangleObject draw designer 
       // Will require the user to click 3 times once for each point 
       // 
       public class MyTriangleObjectDrawDesigner : 
          AnnDrawDesigner    // must derive from AnnDrawDesigner or one of its derived classes 
       { 
          // private variables 
          // 
          // we need to keep track on next point to add 
          private int _clickCount; 
          // 
          // constructor 
          // 
          public MyTriangleObjectDrawDesigner() 
          { 
                _clickCount = 0; 
          } 
          // 
          // AnnDrawDesigner overrides 
          // 
          public override bool MouseDown(MouseEventArgs e) 
          { 
             bool handled = false; 
             // only process left button clicks 
             if(e.Button == MouseButtons.Left) 
             { 
                // check if we have not started drawing yet, DrawObject will be null 
                if(DrawObject == null) 
                { 
                   // yes, create a new MyTriangleObject from ObjectTemplate 
                   MyTriangleObject obj = ObjectTemplate.Clone() as MyTriangleObject; 
                   // setup the points 
                   AnnPoint pt = GetLogicalAnnPoint(e.X, e.Y, obj.FirstPoint.Unit); 
                   obj.FirstPoint = pt; 
                   obj.SecondPoint = pt; 
                   obj.ThirdPoint = pt; 
                   // start drawing this new object 
                   StartWorking(obj); 
                   handled = true; 
                   // we processed first click 
                   _clickCount++; 
                } 
                else 
                { 
                   // an object is already being drawn, so process next click 
                   // get our object and assign next point to it 
                   MyTriangleObject obj = DrawObject as MyTriangleObject; 
                   AnnPoint pt = GetLogicalAnnPoint(e.X, e.Y, obj.FirstPoint.Unit); 
                   if(_clickCount == 1) 
                   { 
                      // second point 
                      obj.SecondPoint = pt; 
                      _clickCount++; 
                   } 
                   else if(_clickCount == 2) 
                   { 
                      // third point 
                      obj.ThirdPoint = pt; 
                      // we are done! 
                      EndWorking(); 
                   } 
                } 
             } 
             else 
             { 
                // we want to cancel the drawing if any other button has been clicked 
                if(DrawObject != null) 
                { 
                   Cancel(); 
                   handled = true; 
                } 
             } 
             return handled; 
          } 
          public override bool MouseMove(MouseEventArgs e) 
          { 
             bool handled = false; 
             // check if we are already drawing an object 
             if(DrawObject != null) 
             { 
                // yes, get this object and assign the next point 
                // first, save the old invalid rectangle 
                Rectangle rcOld = DrawObject.InvalidRectangle; 
                // get out object and assign the point 
                MyTriangleObject obj = DrawObject as MyTriangleObject; 
                AnnPoint pt = GetLogicalAnnPoint(e.X, e.Y, obj.FirstPoint.Unit); 
                if(_clickCount == 1) 
                   obj.SecondPoint = pt; 
                else if(_clickCount == 2) 
                   obj.ThirdPoint = pt; 
                // get the new invalid rectangle 
                Rectangle rcNew = DrawObject.InvalidRectangle; 
                // continue drawing this object 
                Working(Rectangle.Union(rcOld, rcNew)); 
                handled = true; 
             } 
             return handled; 
          } 
          public override bool MouseUp(MouseEventArgs e) 
          { 
             // we do not need to do anything special on mouse up. 
             // so just see if we are drawing to return true (we handled it) 
             bool handled = false; 
             if(DrawObject == null) 
                handled = true; 
             return handled; 
          } 
       } 
    } 

  5. Next, the edit designer, add a new class to your project, name this class "MyTriangleObjectEditDesigner" and add the following code:

    C#
    VB
    Imports System 
    Imports System.Drawing 
    Imports Leadtools.Annotations 
    ' 
    ' MyTriangleObject edit designer 
    ' User can click on any of the points and move them around as well as clicking and dragging the object itself. 
    ' 
    Public Class MyTriangleObjectEditDesigner 
       Inherits AnnEditDesigner    ' must derive from AnnEditDesigner or one of its derived classes 
       ' 
       ' constructor 
       ' 
       Public Sub New() 
       End Sub 
       ' 
       ' AnnEditDesigner overrides 
       ' 
       Public Overrides ReadOnly Property ControlPointCount() As Integer 
          Get 
             ' return the number of control points we need 
             ' in this case 3, one for each point in our triangle 
             Return 3 
          End Get 
       End Property 
       Public Overrides Function GetControlPointsLocation() As AnnPoint() 
          ' return the position of these control points 
          ' in this case, same as the points from our object 
          Dim obj As MyTriangleObject = DirectCast(EditObject, MyTriangleObject) 
          Return New AnnPoint() _ 
          { _ 
             obj.FirstPoint, _ 
             obj.SecondPoint, _ 
             obj.ThirdPoint() _ 
          } 
       End Property 
       Protected Overrides Sub MoveControlPoint(ByVal controlPointIndex As Integer, ByVal pt As AnnPoint) 
          ' user has clicked and moved a point. 
          ' based on the index, we can tell if the user dragged the first, second or third point 
          Dim obj As MyTriangleObject = DirectCast(EditObject, MyTriangleObject) 
          Select Case (controlPointIndex) 
             Case 0 
                ' first point 
                obj.FirstPoint = pt.ConvertTo(Container.UnitConverter, obj.FirstPoint.Unit) 
             Case 1 
                ' second point 
                obj.SecondPoint = pt.ConvertTo(Container.UnitConverter, obj.SecondPoint.Unit) 
             Case 2 
                ' third point 
                obj.ThirdPoint = pt.ConvertTo(Container.UnitConverter, obj.ThirdPoint.Unit) 
          End Select 
       End Sub 
       ' Note, we will not override Move or MoveName since the default implementation is good enough for our object 
    End Class 
    using System; 
    using System.Drawing; 
    using Leadtools.Annotations; 
    namespace MyNamespace 
    { 
       // 
       // MyTriangleObject edit designer 
       // The user can click on any of the points and move them around, as well as clicking and dragging the object itself. 
       // 
       public class MyTriangleObjectEditDesigner : 
          AnnEditDesigner    // must derive from AnnEditDesigner or one of its derived classes 
       { 
          // 
          // constructor 
          // 
          public MyTriangleObjectEditDesigner() 
          { 
          } 
          // 
          // AnnEditDesigner overrides 
          // 
          public override int ControlPointCount 
          { 
             get 
             { 
                // return the number of control points we need 
                // in this case 3, one for each point in our triangle 
                return 3; 
             } 
          } 
          public override AnnPoint[] GetControlPointsLocation() 
          { 
             // return the position of these control points 
             // in this case, same as the points from our object 
             MyTriangleObject obj = EditObject as MyTriangleObject; 
             return new AnnPoint[] 
             { 
                obj.FirstPoint, 
                obj.SecondPoint, 
                obj.ThirdPoint 
             }; 
          } 
          protected override void MoveControlPoint(int controlPointIndex, AnnPoint pt) 
          { 
             // user has clicked and moved a point. 
             // based on the index, we can tell if the user dragged the first, second or third point 
             MyTriangleObject obj = EditObject as MyTriangleObject; 
             switch(controlPointIndex) 
             { 
                case 0: 
                   // first point 
                   obj.FirstPoint = pt.ConvertTo(Container.UnitConverter, obj.FirstPoint.Unit); 
                   break; 
                case 1: 
                   // second point 
                   obj.SecondPoint = pt.ConvertTo(Container.UnitConverter, obj.SecondPoint.Unit); 
                   break; 
                case 2: 
                   // third point 
                   obj.ThirdPoint = pt.ConvertTo(Container.UnitConverter, obj.ThirdPoint.Unit); 
                   break; 
             } 
          } 
          // Note, we will not override Move or MoveName since the default implementation is good enough for our object 
       } 
    } 

    Now we are going to add another object. The CheckBox class will use the ControlPaint class to draw a check box along with a text string. Our class will not support a pen, but a brush and a text. We will use the AnnTextObject as the base class for our CheckBox class.

  6. Start by adding a new class to your project, name this class MyCheckBoxObject. The following is the source code for this class:

    C#
    VB
    Imports System 
    Imports System.Drawing 
    Imports System.Drawing.Drawing2D 
    Imports System.Windows.Forms 
    Imports System.Runtime.Serialization 
    Imports Leadtools.Annotations 
    ' 
    ' CheckBox annotation object class 
    ' our class will use the ControlPaint class to draw a check box along with text. 
    ' our class will not support a pen, but a brush and a text 
    ' 
    ' our class must be serializable to play well with the annotation load/save and undo/redo features 
    <Serializable()> _ 
    Public Class MyCheckBoxObject 
       Inherits AnnTextObject    ' We will derive from AnnTextObject so we already have the text 
       ' 
       ' our private variables 
       ' 
       ' the checkbox state 
       <NonSerialized()> Private _checked As Boolean 
       ' 
       ' constructor 
       ' 
       Public Sub New() 
          ' supportsPen = no, supportsBrush = yes, supportsFont = yes 
          MyBase.New( _ 
             False, _ 
             True, _ 
             True) 
          ' initialize the state 
          _checked = False 
       End Sub 
       ' 
       ' ISerializable implementation 
       ' 
       Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext) 
          MyBase.New(info, context)    ' do not forget to call the base class version 
          ' we need to deserialize our private variables here 
          _checked = info.GetBoolean("Checked") 
       End Sub 
       Public Overrides Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) 
          ' we need to serialize our private variables here 
          ' call the base class version 
          MyBase.GetObjectData(info, context) 
          ' serialize the state 
          info.AddValue("Checked", _checked) 
       End Sub 
       ' 
       ' accessors 
       ' 
       Public Property Checked() As Boolean 
          Get 
             Return _checked 
          End Get 
          Set(ByVal Value As Boolean) 
             _checked = Value 
          End Set 
       End Property 
       ' 
       ' AnnObject overrides 
       ' 
       Protected Overrides Function Create() As AnnObject 
          ' must return a new instance of our class 
          Return New MyCheckBoxObject 
       End Function 
       Public Overrides Function Clone() As Object 
          ' override the clone method 
          ' first call the base implementation 
          Dim obj As MyCheckBoxObject = DirectCast(MyBase.Clone(), MyCheckBoxObject) 
          Return obj 
       End Function 
       ' we will not override GetGraphicsPath, the base class version is 
       ' suitable for hittesting and finding the object bounding rectangle. 
       ' however, we will override DrawObject to manually paint the object 
       Protected Overrides Sub DrawObject(ByVal g As Graphics) 
          ' begin the drawing 
          Dim gState As GraphicsState = BeginDraw(g) 
          If (Not gState Is Nothing) Then 
             ' get the bounding rectangle in pixels 
             Dim boundsPixels As RectangleF = Bounds.ConvertTo(UnitConverter, AnnUnit.Pixel).ToRectangleF() 
             ' first, see if we have a brush, if so, fill this rectangle 
             If (HasBrush) Then 
                Dim br As Brush = Brush.Create(UnitConverter, Bounds) 
                g.FillRectangle(br, boundsPixels) 
                br.Dispose() 
             End If 
             If (IsNonEmptyRectangle(boundsPixels)) Then 
                ' use the ControlPaint class to paint the check box on the left of the object 
                Dim rc As Rectangle = Rectangle.Round(boundsPixels) 
                If (IsNonEmptyRectangle(rc)) Then 
                   Dim checkBoxRectangle As New Rectangle(rc.Left, rc.Top, rc.Height, rc.Height) 
                   If (Checked) Then 
                      ControlPaint.DrawCheckBox(g, checkBoxRectangle, ButtonState.Checked) 
                   Else 
                      ControlPaint.DrawCheckBox(g, checkBoxRectangle, ButtonState.Normal) 
                   End If 
                   ' update the bounds rectangle 
                   boundsPixels = RectangleF.FromLTRB(checkBoxRectangle.Right, checkBoxRectangle.Top, boundsPixels.Right, boundsPixels.Bottom) 
                End If 
             End If 
             ' get the edge margin in pixels 
             Dim edgeMarginPixels As Single = EdgeMargin.Converted(UnitConverter, AnnUnit.Pixel) 
             boundsPixels.Inflate(-edgeMarginPixels, -edgeMarginPixels) 
             ' finally draw the text 
             If (HasFont AndAlso Not IsNothing(Text) AndAlso Text <> String.Empty AndAlso Text.Length > 0 AndAlso IsNonEmptyRectangle(boundsPixels)) Then 
                Dim sf As StringFormat = DirectCast(StringFormat.GenericDefault.Clone(), StringFormat) 
                sf.Alignment = Alignment 
                sf.LineAlignment = LineAlignment 
                Dim fnt As Font = Font.Create(g, UnitConverter) 
                Dim br As New SolidBrush(TextColor) 
                g.DrawString(Text, fnt, br, boundsPixels, sf) 
                br.Dispose() 
                fnt.Dispose() 
                sf.Dispose() 
             End If 
             EndDraw(g, gState) 
          End If 
       End Sub 
      Shared Function FixRectangle(ByVal rc As RectangleF) As RectangleF 
         If (rc.Left > rc.Right OrElse rc.Top > rc.Bottom) Then 
            Return RectangleF.FromLTRB( _ 
               Math.Min(rc.Left, rc.Right), _ 
               Math.Min(rc.Top, rc.Bottom), _ 
               Math.Max(rc.Left, rc.Right), _ 
               Math.Max(rc.Top, rc.Bottom)) 
         Else 
            Return rc 
         End If 
      End Function 
      Shared Function IsNonEmptyRectangle(ByVal rc As RectangleF) As Boolean 
         Return rc.Width <> 0 AndAlso rc.Height <> 0 
      End Function 
    End Class 
    using System; 
    using System.Drawing; 
    using System.Drawing.Drawing2D; 
    using System.Windows.Forms; 
    using System.Runtime.Serialization; 
    using Leadtools.Annotations; 
    namespace MyNamespace 
    { 
       // 
       // CheckBox annotation object class 
       // our class will use the ControlPaint class to draw a check box along with text. 
       // our class will not support a pen, but a brush and a text 
       // 
       [Serializable] // our class must be serializable to play well with the annotation load/save and undo/redo features 
       public class MyCheckBoxObject : 
          AnnTextObject    // We will derive from AnnTextObject so we already have the text 
       { 
          // 
          // our private variables 
          // 
          // the checkbox state 
          [NonSerialized()] private bool _checked; 
          // 
          // constructor 
          // 
          public MyCheckBoxObject() : 
             base( 
             false,    // no, we do not require a pen 
             true,    // we require a brush 
             true)    // we require a font 
          { 
             // initialize the state 
             _checked = false; 
          } 
          // 
          // ISerializable implementation 
          // 
          protected MyCheckBoxObject(SerializationInfo info, StreamingContext context) : 
          base(info, context)    // do not forget to call the base class version 
          { 
             // we need to deserialize our private variables here 
             _checked = info.GetBoolean("Checked"); 
          } 
          public override void GetObjectData(SerializationInfo info, StreamingContext context) 
          { 
             // we need to serialize our private variables here 
             // call the base class version 
             base.GetObjectData(info, context); 
             // serialize the state 
             info.AddValue("Checked", _checked); 
          } 
          // 
          // accessors 
          // 
          public bool Checked 
          { 
             get 
             { 
                return _checked; 
             } 
             set 
             { 
                _checked = value; 
             } 
          } 
          // 
          // AnnObject overrides 
          // 
          protected override AnnObject Create() 
          { 
             // must return a new instance of our class 
             return new MyCheckBoxObject(); 
          } 
          public override object Clone() 
          { 
             // override the clone method 
             // first call the base implementation 
             MyCheckBoxObject obj = base.Clone() as MyCheckBoxObject; 
             return obj; 
          } 
          // we will not override GetGraphicsPath, the base class version is 
          // suitable for hittesting and finding the object bounding rectangle. 
          // however, we will override DrawObject to manually paint the object 
          protected override void DrawObject(Graphics g) 
          { 
             // begin the drawing 
             GraphicsState gState = BeginDraw(g); 
             if(gState != null) 
             { 
                // get the bounding rectangle in pixels 
                RectangleF boundsPixels = Bounds.ConvertTo(UnitConverter, AnnUnit.Pixel).ToRectangleF(); 
                // first, see if we have a brush, if so, fill this rectangle 
                if(HasBrush) 
                { 
                   using(Brush br = Brush.Create(UnitConverter, Bounds)) 
                   g.FillRectangle(br, boundsPixels); 
                } 
                if(IsNonEmptyRectangle(boundsPixels)) 
                { 
                   // use the ControlPaint class to paint the check box on the left of the object 
                   Rectangle rc = Rectangle.Round(boundsPixels); 
                   if(IsNonEmptyRectangle(rc)) 
                   { 
                      Rectangle checkBoxRectangle = new Rectangle(rc.Left, rc.Top, rc.Height, rc.Height); 
                      ControlPaint.DrawCheckBox(g, checkBoxRectangle, Checked ? ButtonState.Checked: ButtonState.Normal); 
                      // update the bounds rectangle 
                      boundsPixels = RectangleF.FromLTRB(checkBoxRectangle.Right, checkBoxRectangle.Top, boundsPixels.Right, boundsPixels.Bottom); 
                   } 
                } 
                // get the edge margin in pixels 
                float edgeMarginPixels = EdgeMargin.Converted(UnitConverter, AnnUnit.Pixel); 
                boundsPixels.Inflate(-edgeMarginPixels, -edgeMarginPixels); 
                // finally draw the text 
                if(HasFont && Text != null && Text != string.Empty && Text.Length > 0 && IsNonEmptyRectangle(boundsPixels)) 
                { 
                   using(StringFormat sf = StringFormat.GenericDefault.Clone() as StringFormat) 
                   { 
                      sf.Alignment = Alignment; 
                      sf.LineAlignment = LineAlignment; 
                      using(Font font = Font.Create(g, UnitConverter)) 
                      { 
                         using(Brush brush = new SolidBrush(TextColor)) 
                         g.DrawString(Text, font, brush, boundsPixels, sf); 
                      } 
                   } 
                } 
                EndDraw(g, gState); 
             } 
          } 
          static RectangleF FixRectangle(RectangleF rc) 
          { 
             if(rc.Left > rc.Right ||   rc.Top > rc.Bottom) 
                return RectangleF.FromLTRB( 
                   Math.Min(rc.Left, rc.Right), 
                   Math.Min(rc.Top, rc.Bottom), 
                   Math.Max(rc.Left, rc.Right), 
                   Math.Max(rc.Top, rc.Bottom)); 
             else 
                return rc; 
          } 
          static bool IsNonEmptyRectangle(RectangleF rc) 
          { 
             return rc.Width != 0 && rc.Height != 0; 
          } 
       } 
    } 

    We will use the AnnRectangleDrawDesigner and AnnRectangleEditDesigner to draw and edit this class. However, we will add a custom run designer to handle the runtime behavor of this class. At runtime, we want the user to be able to click the CheckBox class and change the checked state.

  7. Add a new class to your project, name this class "MyCheckBoxRunDesigner" and add the following code:

    C#
    VB
    Imports System 
    Imports System.Drawing 
    Imports System.Windows.Forms 
    Imports Leadtools.Annotations 
    ' 
    ' MyCheckBoxObject run designer 
    ' When the user clicks the object, flip the Checked state 
    ' 
    Public Class MyCheckBoxObjectRunDesigner 
       Inherits AnnRunDesigner    ' must derive from AnnRunDesigner or one of its derived classes 
       ' 
       ' constructor 
       ' 
       Public Sub New() 
       End Sub 
       ' 
       ' AnnRunDesigner overrides 
       ' 
       Protected Overrides Sub OnRun(ByVal e As AnnRunDesignerEventArgs) 
          ' OnRun gets called while the user is running the object 
          ' check the state 
          If (e.OperationStatus = AnnDesignerOperationStatus.End) Then 
             ' End is when the user clicks the object by default, flip the Checked state 
             Dim obj As MyCheckBoxObject = DirectCast(e.Object, MyCheckBoxObject) 
             obj.Checked = Not obj.Checked 
             ' repaint this object 
             Owner.Invalidate(obj.InvalidRectangle) 
             ' we chose to ignore the default run for this object 
             ' not setting e.Cancel to true will play the hyperlink 
             e.Cancel = True 
          End If 
          MyBase.OnRun(e) 
       End Sub 
    End Class 
    using System; 
    using System.Drawing; 
    using System.Windows.Forms; 
    using Leadtools.Annotations; 
    namespace MyNamespace 
    { 
       // 
       // MyCheckBoxObject run designer 
       // When the user clicks the object, flip the Checked state 
       // 
       public class MyCheckBoxObjectRunDesigner : 
       AnnRunDesigner    // must derive from AnnRunDesigner or one of its derived classes 
       { 
          // 
          // constructor 
          // 
          public MyCheckBoxObjectRunDesigner() 
          { 
          } 
          // 
          // AnnRunDesigner overrides 
          // 
          protected override void OnRun(AnnRunDesignerEventArgs e) 
          { 
             // OnRun gets called while the user is running the object 
             // check the state 
             if(e.OperationStatus == AnnDesignerOperationStatus.End) 
             { 
                // End is when the user clicks the object by default, flip the Checked state 
                MyCheckBoxObject obj = e.Object as MyCheckBoxObject; 
                obj.Checked = !obj.Checked; 
                // repaint this object 
                Owner.Invalidate(obj.InvalidRectangle); 
                // we chose to ignore the default run for this object 
                // not setting e.Cancel to true will play the hyperlink 
                e.Cancel = true; 
             } 
             base.OnRun(e); 
          } 
       } 
    } 

  8. Now let us test these new objects. Add a new RasterImageViewer control to your main form along with four buttons (Text = "Save", "Load", "Clear" and "Run/Design".

    At the top of the Form1 class, add the following:

    C#
    VB
    Imports System.IO 
    Imports Leadtools 
    Imports Leadtools.Codecs 
    Imports Leadtools.WinForms 
    Imports Leadtools.Annotations 
    using System.IO; 
    using Leadtools; 
    using Leadtools.Codecs; 
    using Leadtools.WinForms; 
    using Leadtools.Annotations; 
    using MyNamespace; 

  9. Add a new handler for Form1 Load event and add the following code:

    C#
    VB
    /// Private theManager As AnnAutomationManager 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
       ' load an image into the viewer 
       Dim codecs As New RasterCodecs 
       RasterImageViewer1.Image = codecs.Load("C:\Users\Public\Documents\LEADTOOLS Images\Sample1.cmp") 
       ' create and setup the automation manager 
       theManager = New AnnAutomationManager 
       ' Create the default (all) automation objects. 
       theManager.CreateDefaultObjects() 
       ' add our own Triangle and CheckBox as automation objects 
       AddMyTriangleAutomationObject(theManager) 
       AddMyCheckBoxAutomationObject(theManager) 
       ' create the toolbar and add it to the form 
       theManager.CreateToolBar() 
       Controls.Add(theManager.ToolBar) 
       theManager.ToolBar.BringToFront() 
       ' setup the automation (will create the container as well) 
       Dim automation As New AnnAutomation(theManager, RasterImageViewer1) 
       ' setup this automation as the active one 
       automation.Active = True 
    End Sub 
    Private Sub AddMyTriangleAutomationObject(ByVal manager As AnnAutomationManager) 
       Dim autObj As New AnnAutomationObject 
       ' setup the ID 
       autObj.Id = AnnAutomationManager.UserObjectId 
       ' give it a friendly name 
       autObj.Name = "Triangle" 
       ' setup the object template 
       ' this the object that will be used when drawing new MyTriangleObject.    so, setup the pen and brush as desired 
       Dim obj As New MyTriangleObject 
       obj.Pen = New AnnPen(Color.Blue, New AnnLength(2, AnnUnit.Pixel)) 
       obj.Brush = New AnnSolidBrush(Color.Yellow) 
       autObj.Object = obj 
       ' setup the draw, edit and run designers type 
       autObj.DrawDesignerType = GetType(MyTriangleObjectDrawDesigner) 
       autObj.EditDesignerType = GetType(MyTriangleObjectEditDesigner) 
       ' we will use the default run designer for this object 
       autObj.RunDesignerType = GetType(AnnRunDesigner) 
       ' we need a toolbar image, so create one 
       Dim btmp As New Bitmap(16, 16) 
       Dim g As Graphics = Graphics.FromImage(btmp) 
       g.FillRectangle(Brushes.Magenta, 0, 0, 16, 16) 
       g.DrawLine(Pens.Black, 8, 2, 14, 14) 
       g.DrawLine(Pens.Black, 14, 14, 2, 14) 
       g.DrawLine(Pens.Black, 2, 14, 8, 2) 
       g.Dispose() 
       autObj.ToolBarImage = btmp 
       ' setup the toolbar button tooltip text 
       autObj.ToolBarToolTipText = "Triangle" 
       ' setup the cursor used when drawing this object 
       autObj.DrawCursor = Cursors.Cross 
       ' setup the context menu for this object 
       ' we will use the default context menu 
       autObj.ContextMenu = AnnAutomationManager.CreateDefaultObjectContextMenu(autObj.Id) 
       ' finally add this object to the automation objects of the manager 
       manager.Objects.Add(autObj) 
                       End Sub 
                       Private Sub AddMyCheckBoxAutomationObject(ByVal manager As AnnAutomationManager) 
       Dim autObj As New AnnAutomationObject 
       ' setup the ID 
       autObj.Id = AnnAutomationManager.UserObjectId + 1 
       ' give it a friendly name 
       autObj.Name = "CheckBox" 
       ' setup the object template 
       ' this the object that will be used when drawing new MyCheckBoxObject.    so, setup the brush, font and text 
       Dim obj As New MyCheckBoxObject 
       obj.Checked = False 
       obj.Brush = New AnnSolidBrush(SystemColors.Control) 
       obj.Text = "CheckBox" 
       obj.TextColor = SystemColors.ControlText 
       obj.Font = New AnnFont("Arial", New AnnLength(8, AnnUnit.Point), FontStyle.Regular) 
       obj.Alignment = StringAlignment.Near 
       obj.LineAlignment = StringAlignment.Center 
       autObj.Object = obj 
       ' setup the draw, edit and run designers type 
       ' note, MyCheckBoxObject will use the default rectangle draw and edit designers 
       autObj.DrawDesignerType = GetType(AnnRectangleDrawDesigner) 
       autObj.EditDesignerType = GetType(AnnRectangleEditDesigner) 
       ' use our run designer 
       autObj.RunDesignerType = GetType(MyCheckBoxObjectRunDesigner) 
       ' we need a toolbar image, so create one 
       Dim btmp As New Bitmap(16, 16) 
       Dim g As Graphics = Graphics.FromImage(btmp) 
       g.FillRectangle(Brushes.Magenta, 0, 0, 16, 16) 
       ControlPaint.DrawCheckBox(g, 0, 0, 16, 16, ButtonState.Flat Or ButtonState.Checked) 
       g.Dispose() 
       autObj.ToolBarImage = btmp 
       ' setup the toolbar button tooltip text 
       autObj.ToolBarToolTipText = "CheckBox" 
       ' setup the cursor used when drawing this object 
       autObj.DrawCursor = Cursors.Cross 
       ' setup the context menu for this object 
       ' we will insert a new menu item for "Checked" before the properties menu item 
       Dim cm As ContextMenu = AnnAutomationManager.CreateDefaultObjectContextMenu(autObj.Id) 
       ' add a handler for the Popup event so we can check/uncheck our new menu item 
       AddHandler cm.Popup, AddressOf checkedMenuItem_Popup 
       ' first a new separator 2 items from the end 
       cm.MenuItems.Add(cm.MenuItems.Count - 2, New MenuItem("-")) 
       ' and our menu item 
       Dim checkedMenuItem As New MenuItem("Checked") 
       AddHandler checkedMenuItem.Click, AddressOf checkedMenuItem_Click 
       cm.MenuItems.Add(cm.MenuItems.Count - 2, checkedMenuItem) 
       autObj.ContextMenu = cm 
       ' finally add this object to the automation objects of the manager 
       manager.Objects.Add(autObj) 
                       End Sub 
                       Private Sub checkedMenuItem_Popup(ByVal sender As Object, ByVal e As EventArgs) 
       ' check/uncheck the Checked menu item depending on the object state 
       Dim cm As ContextMenu = DirectCast(sender, ContextMenu) 
       Dim automation As AnnAutomation = theManager.Automations(0) 
       Dim obj As MyCheckBoxObject = DirectCast(automation.CurrentEditObject, MyCheckBoxObject) 
       cm.MenuItems(cm.MenuItems.Count - 3).Checked = obj.Checked 
                       End Sub 
                       Private Sub checkedMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) 
       ' check/uncheck the object 
       ' do not forget to add an undo node 
       Dim automation As AnnAutomation = theManager.Automations(0) 
       Dim obj As MyCheckBoxObject = DirectCast(automation.CurrentEditObject, MyCheckBoxObject) 
       automation.BeginUndo() 
       obj.Checked = Not obj.Checked 
       automation.EndUndo() 
       automation.Viewer.Invalidate(obj.InvalidRectangle) 
    End Sub 
    private AnnAutomationManager theManager; 
    private void Form1_Load(object sender, System.EventArgs e) 
    { 
       // load an image into the viewer 
       RasterCodecs codecs = new RasterCodecs(); 
       rasterImageViewer1.Image = codecs.Load(@"C:\Users\Public\Documents\LEADTOOLS Images\Sample1.cmp"); 
       // create and setup the automation manager 
       theManager = new AnnAutomationManager(); 
       // Create the default (all) automation objects. 
       theManager.CreateDefaultObjects(); 
       // add our own Triangle and CheckBox as automation objects 
       AddMyTriangleAutomationObject(theManager); 
       AddMyCheckBoxAutomationObject(theManager); 
       // create the toolbar and add it to the form 
       theManager.CreateToolBar(); 
       Controls.Add(theManager.ToolBar); 
       theManager.ToolBar.BringToFront(); 
       // setup the automation (will create the container as well) 
       AnnAutomation automation = new AnnAutomation(theManager, rasterImageViewer1); 
       // setup this automation as the active one 
       automation.Active = true; 
    } 
    private void AddMyTriangleAutomationObject(AnnAutomationManager manager) 
    { 
       AnnAutomationObject autObj = new AnnAutomationObject(); 
       // setup the ID 
       autObj.Id = AnnAutomationManager.UserObjectId; 
       // give it a friendly name 
       autObj.Name = "Triangle"; 
       // setup the object template 
       // this the object that will be used when drawing new MyTriangleObject.    so, setup the pen and brush as desired 
       MyTriangleObject obj = new MyTriangleObject(); 
       obj.Pen = new AnnPen(Color.Blue, new AnnLength(2, AnnUnit.Pixel)); 
       obj.Brush = new AnnSolidBrush(Color.Yellow); 
       autObj.Object = obj; 
       // setup the draw, edit and run designers type 
       autObj.DrawDesignerType = typeof(MyTriangleObjectDrawDesigner); 
       autObj.EditDesignerType = typeof(MyTriangleObjectEditDesigner); 
       // we will use the default run designer for this object 
       autObj.RunDesignerType = typeof(AnnRunDesigner); 
       // we need a toolbar image, so create one 
       Bitmap btmp = new Bitmap(16, 16); 
       using(Graphics g = Graphics.FromImage(btmp)) 
       { 
          g.FillRectangle(Brushes.Magenta, 0, 0, 16, 16); 
          g.DrawLine(Pens.Black, 8, 2, 14, 14); 
          g.DrawLine(Pens.Black, 14, 14, 2, 14); 
          g.DrawLine(Pens.Black, 2, 14, 8, 2); 
       } 
       autObj.ToolBarImage = btmp; 
       // setup the toolbar button tooltip text 
       autObj.ToolBarToolTipText = "Triangle"; 
       // setup the cursor used when drawing this object 
       autObj.DrawCursor = Cursors.Cross; 
       // setup the context menu for this object 
       // we will use the default context menu 
       autObj.ContextMenu = AnnAutomationManager.CreateDefaultObjectContextMenu(autObj.Id); 
       // finally add this object to the automation objects of the manager 
       manager.Objects.Add(autObj); 
    } 
    private void AddMyCheckBoxAutomationObject(AnnAutomationManager manager) 
    { 
       AnnAutomationObject autObj = new AnnAutomationObject(); 
       // setup the ID 
       autObj.Id = AnnAutomationManager.UserObjectId + 1; 
       // give it a friendly name 
       autObj.Name = "CheckBox"; 
       // setup the object template 
       // this the object that will be used when drawing new MyCheckBoxObject.    so, setup the brush, font and text 
       MyCheckBoxObject obj = new MyCheckBoxObject(); 
       obj.Checked = false; 
       obj.Brush = new AnnSolidBrush(SystemColors.Control); 
       obj.Text = "CheckBox"; 
       obj.TextColor = SystemColors.ControlText; 
       obj.Font = new AnnFont("Arial", new AnnLength(8, AnnUnit.Point), FontStyle.Regular); 
       obj.Alignment = StringAlignment.Near; 
       obj.LineAlignment = StringAlignment.Center; 
       autObj.Object = obj; 
       // setup the draw, edit and run designers type 
       // note, MyCheckBoxObject will use the default rectangle draw and edit designers 
       autObj.DrawDesignerType = typeof(AnnRectangleDrawDesigner); 
       autObj.EditDesignerType = typeof(AnnRectangleEditDesigner); 
       // use our run designer 
       autObj.RunDesignerType = typeof(MyCheckBoxObjectRunDesigner); 
       // we need a toolbar image, so create one 
       Bitmap btmp = new Bitmap(16, 16); 
       using(Graphics g = Graphics.FromImage(btmp)) 
       { 
          g.FillRectangle(Brushes.Magenta, 0, 0, 16, 16); 
          ControlPaint.DrawCheckBox(g, 0, 0, 16, 16, ButtonState.Flat |   ButtonState.Checked); 
       } 
       autObj.ToolBarImage = btmp; 
       // setup the toolbar button tooltip text 
       autObj.ToolBarToolTipText = "CheckBox"; 
       // setup the cursor used when drawing this object 
       autObj.DrawCursor = Cursors.Cross; 
       // setup the context menu for this object 
       // we will insert a new menu item for "Checked" before the properties menu item 
       ContextMenu cm = AnnAutomationManager.CreateDefaultObjectContextMenu(autObj.Id); 
       // add a handler for the Popup event so we can check/uncheck our new menu item 
       cm.Popup += new EventHandler(checkedMenuItem_Popup); 
       // first a new seperator 2 items from the end 
       cm.MenuItems.Add(cm.MenuItems.Count - 2, new MenuItem("-")); 
       // and our menu item 
       MenuItem checkedMenuItem = new MenuItem("Checked"); 
       checkedMenuItem.Click += new EventHandler(checkedMenuItem_Click); 
       cm.MenuItems.Add(cm.MenuItems.Count - 2, checkedMenuItem); 
       autObj.ContextMenu = cm; 
       // finally add this object to the automation objects of the manager 
       manager.Objects.Add(autObj); 
    } 
    private void checkedMenuItem_Popup(object sender, EventArgs e) 
    { 
       // check/uncheck the Checked menu item depending on the object state 
       ContextMenu cm = sender as ContextMenu; 
       AnnAutomation automation = theManager.Automations[0]; 
       MyCheckBoxObject obj = automation.CurrentEditObject as MyCheckBoxObject; 
       cm.MenuItems[cm.MenuItems.Count - 3].Checked = obj.Checked; 
    } 
    private void checkedMenuItem_Click(object sender, EventArgs e) 
    { 
       // check/uncheck the object 
       // do not forget to add an undo node 
       AnnAutomation automation = theManager.Automations[0]; 
       MyCheckBoxObject obj = automation.CurrentEditObject as MyCheckBoxObject; 
       automation.BeginUndo(); 
       obj.Checked = !obj.Checked; 
       automation.EndUndo(); 
       automation.Viewer.Invalidate(obj.InvalidRectangle); 
    } 

  10. Add event handlers for Button1, Button2, Button3 and Button3 and add the following code:

    C#
    VB
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
       ' Save button clicked 
       Dim codecs As New AnnCodecs 
       codecs.Save("C:\Test.ann", theManager.Automations(0).Container, AnnCodecsFormat.Serialize, 1, AnnCodecsSavePageMode.Overwrite) 
       RasterImageViewer1.Invalidate() 
    End Sub  
                     
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
       ' Load button clicked 
       Dim codecs As New AnnCodecs 
       theManager.Automations(0).Container.Objects.Clear() 
       codecs.Load("C:\Test.ann", theManager.Automations(0).Container, 1) 
       RasterImageViewer1.Invalidate() 
    End Sub 
                     
    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click 
       ' Clear button clicked 
       theManager.Automations(0).Container.Objects.Clear() 
       RasterImageViewer1.Invalidate() 
       Dim editDesigner As AnnEditDesigner = TryCast(theManager.Automations(0).CurrentDesigner, AnnEditDesigner) 
       If Not editDesigner Is Nothing Then 
         editDesigner.End() 
       End If 
    End Sub 
                     
    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click 
       ' Run/Design button clicked 
       If (theManager.UserMode = AnnUserMode.Design) Then 
          theManager.UserMode = AnnUserMode.Run 
       Else 
          theManager.UserMode = AnnUserMode.Design 
       End If 
    End Sub 
    private void button1_Click(object sender, System.EventArgs e) 
    { 
       // Save button clicked 
       AnnCodecs codecs = new AnnCodecs(); 
       codecs.Save(@"C:\Test.ann", theManager.Automations[0].Container, AnnCodecsFormat.Serialize, 1, AnnCodecsSavePageMode.Overwrite); 
       rasterImageViewer1.Invalidate(); 
    } 
    private void button2_Click(object sender, System.EventArgs e) 
    { 
       // Load button clicked 
       AnnCodecs codecs = new AnnCodecs(); 
       theManager.Automations[0].Container.Objects.Clear(); 
       codecs.Load(@"C:\Test.ann", theManager.Automations[0].Container, 1); 
       rasterImageViewer1.Invalidate(); 
    } 
    private void button3_Click(object sender, System.EventArgs e) 
    { 
       // Clear button clicked 
       theManager.Automations[0].Container.Objects.Clear(); 
       rasterImageViewer1.Invalidate(); 
       AnnEditDesigner editDesigner = theManager.Automations[0].CurrentDesigner as AnnEditDesigner; 
       if(editDesigner != null) 
       { 
         editDesigner.End(); 
       }     
    } 
    private void button4_Click(object sender, System.EventArgs e) 
    { 
       // Run/Design button clicked 
       theManager.UserMode = theManager.UserMode == AnnUserMode.Design ? AnnUserMode.Run : AnnUserMode.Design; 
    } 

  11. Build and run the application to test it.

Products | Support | Contact Us | Copyright Notices
© 1991-2017 LEAD Technologies, Inc. All Rights Reserved.
{TOC}
Click or drag to resize