context: // Copyright (c) 2007 Michael Chapman
  
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  
  using System;
  using System.ComponentModel;
  using System.Diagnostics;
  using System.Drawing;
  using System.Globalization;
  using System.Text;
  using System.Windows.Forms; 
  using System.Windows.Forms.VisualStyles;
  
  
  namespace IPAddressControlLib
  {
     [DesignerAttribute( typeof( IPAddressControlDesigner ) )]
     public class IPAddressControl : Control
     {
        #region Public Constants
  
        public const int FieldCount = 4;
  
        #endregion // Public Constants
  
        #region Public Events
  
        public event EventHandler<FieldChangedEventArgs> FieldChangedEvent;
  
        #endregion //Public Events
  
        #region Public Properties
  
        [Browsable( true )]
        public bool AllowInternalTab
        {
           get
           {
              foreach ( FieldControl fc in _fieldControls )
              {
                 return fc.TabStop;
              }
  
              return false;
           }
           set
           {
              foreach ( FieldControl fc in _fieldControls )
              {
                 fc.TabStop = value;
              }
           }
        }
  
        [Browsable( true )]
        public bool AnyBlank
        {
           get
           {
              foreach ( FieldControl fc in _fieldControls )
              {
                 if ( fc.Blank )
                 {
                    return true;
                 }
              }
  
              return false;
           }
        }
  
        [Browsable( true )]
        public bool AutoHeight
        {
           get { return _autoHeight; }
           set
           {
              _autoHeight= value;
  
              if ( _autoHeight )
              {
                 AdjustSize();
              }
           }
        }
  
        [Browsable( false )]
        public int Baseline
        {
           get 
           {
  
  
              VisualStyleRenderer renderer = new VisualStyleRenderer(VisualStyleElement.TextBox.TextEdit.Normal);
  
              Graphics dc = Graphics.FromHwnd(Handle);
              dc.GetHdc();
              TextMetrics textMetric = renderer.GetTextMetrics(dc);
              dc.ReleaseHdc();
  
              int offset = textMetric.Ascent + 1;
  
              switch ( BorderStyle )
              {
                 case BorderStyle.Fixed3D:
                    offset += Fixed3DOffset.Height;
                    break;
                 case BorderStyle.FixedSingle:
                    offset += FixedSingleOffset.Height;
                    break;
              }
  
              return offset;
           }
        }
  
        [Browsable( true )]
        public bool Blank
        {
           get
           {
              foreach ( FieldControl fc in _fieldControls )
              {
                 if ( !fc.Blank )
                 {
                    return false;
                 }
              }
  
              return true;
           }
        }
  
        [Browsable( true )]
        public BorderStyle BorderStyle
        {
           get { return _borderStyle; }
           set
           {
              _borderStyle = value;
              AdjustSize();
              Invalidate();
           }
        }
  
        [Browsable( false )]
        public override bool Focused
        {
           get
           {
              foreach ( FieldControl fc in _fieldControls )
              {
                 if ( fc.Focused )
                 {
                    return true;
                 }
              }
  
              return false;
           }
        }
  
        [Browsable( true )]
        public override Size MinimumSize
        {
           get { return CalculateMinimumSize(); }
        }
  
        [Browsable( true )]
        public bool ReadOnly
        {
           get { return _readOnly; }
           set
           {
              _readOnly = value;
  
              foreach ( FieldControl fc in _fieldControls )
              {
                 fc.ReadOnly = _readOnly;
              }
  
              foreach ( DotControl dc in _dotControls )
              {
                 dc.ReadOnly = _readOnly;
              }
  
              Invalidate();
           }
        }
  
        [Bindable(true)]
        [Browsable(true)]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Visible )]
        public override string Text
        {
           get
           {
              StringBuilder sb = new StringBuilder(); ;
  
              for ( int index = 0; index < _fieldControls.Length; ++index )
              {
                 sb.Append( _fieldControls[ index ].Text );
  
                 if ( index < _dotControls.Length )
                 {
                    sb.Append( _dotControls[ index ].Text );
                 }
              }
  
              return sb.ToString();
           }
           set
           {
              Parse( value );
           }
        }
  
        #endregion // Public Properties
  
        #region Public Methods
  
        public void Clear()
        {
           foreach ( FieldControl fc in _fieldControls )
           {
              fc.Clear();
           }
        }
  
        public byte[] GetAddressBytes()
        {
           byte[] bytes = new byte[FieldCount];
  
           for ( int index = 0; index < FieldCount; ++index )
           {
              bytes[index] = _fieldControls[index].Value;
           }
  
           return bytes;
        }
  
        [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Naming", "CA1720", Justification = "Prefer to use bytes as a variable name." )]
        public void SetAddressBytes( byte[] bytes )
        {
           Clear();
  
           if ( bytes == null )
           {
              return;
           }
  
           int length = Math.Min( FieldCount, bytes.Length );
  
           for ( int i = 0; i < length; ++i )
           {
              _fieldControls[i].Text = bytes[i].ToString( CultureInfo.InvariantCulture );
           }
        }
  
        public void SetFieldFocus( int fieldIndex )
        {
           if ( ( fieldIndex >= 0 ) && ( fieldIndex < FieldCount ) )
           {
              _fieldControls[fieldIndex].TakeFocus( Direction.Forward, Selection.All );
           }
        }
  
        public void SetFieldRange( int fieldIndex, byte rangeLower, byte rangeUpper )
        {
           if ( ( fieldIndex >= 0 ) && ( fieldIndex < FieldCount ) )
           {
              _fieldControls[fieldIndex].RangeLower = rangeLower;
              _fieldControls[fieldIndex].RangeUpper = rangeUpper;
           }
        }
  
        public override string ToString()
        {
           StringBuilder sb = new StringBuilder();
  
           for ( int index = 0; index < FieldCount; ++index )
           {
              sb.Append( _fieldControls[index].ToString() );
  
              if ( index < _dotControls.Length )
              {
                 sb.Append( _dotControls[index].ToString() );
              }
           }
  
           return sb.ToString();
        }
  
        #endregion Public Methods
  
        #region Constructors
  
        public IPAddressControl()
        {
           BackColor = SystemColors.Window;
  
           ResetBackColorChanged();
  
           for ( int index = 0; index < _fieldControls.Length; ++index )
           {
              _fieldControls[index] = new FieldControl();
  
              _fieldControls[index].CreateControl();
  
              _fieldControls[index].FieldIndex = index;
              _fieldControls[index].Name = "FieldControl" + index.ToString( CultureInfo.InvariantCulture );
              _fieldControls[index].Parent = this;
  
              _fieldControls[index].CedeFocusEvent += new EventHandler<CedeFocusEventArgs>( OnCedeFocus );
              _fieldControls[index].Click += new EventHandler( OnSubControlClicked );
              _fieldControls[index].DoubleClick += new EventHandler( OnSubControlDoubleClicked );
              _fieldControls[index].GotFocus += new EventHandler( OnFieldGotFocus );
              _fieldControls[index].KeyDown += new KeyEventHandler( OnFieldKeyDown );
              _fieldControls[index].KeyPress += new KeyPressEventHandler( OnFieldKeyPressed );
              _fieldControls[index].KeyUp += new KeyEventHandler( OnFieldKeyUp );
              _fieldControls[index].LostFocus += new EventHandler( OnFieldLostFocus );
              _fieldControls[index].MouseClick += new MouseEventHandler( OnSubControlMouseClicked );
              _fieldControls[index].MouseDoubleClick += new MouseEventHandler( OnSubControlMouseDoubleClicked );
              _fieldControls[index].MouseEnter += new EventHandler( OnSubControlMouseEntered );
              _fieldControls[index].MouseHover += new EventHandler( OnSubControlMouseHovered );
              _fieldControls[index].MouseLeave += new EventHandler( OnSubControlMouseLeft );
              _fieldControls[index].MouseMove += new MouseEventHandler( OnSubControlMouseMoved );
              _fieldControls[index].PreviewKeyDown += new PreviewKeyDownEventHandler( OnFieldPreviewKeyDown );
              _fieldControls[index].TextChangedEvent += new EventHandler<TextChangedEventArgs>( OnFieldTextChanged );
  
              Controls.Add( _fieldControls[index] );
  
              if ( index < ( FieldCount - 1 ) )
              {
                 _dotControls[index] = new DotControl();
  
                 _dotControls[index].CreateControl();
  
                 _dotControls[index].Name = "DotControl" + index.ToString( CultureInfo.InvariantCulture );
                 _dotControls[index].Parent = this;
  
                 _dotControls[index].Click += new EventHandler( OnSubControlClicked );
                 _dotControls[index].DoubleClick += new EventHandler( OnSubControlDoubleClicked );
                 _dotControls[index].MouseClick += new MouseEventHandler( OnSubControlMouseClicked );
                 _dotControls[index].MouseDoubleClick += new MouseEventHandler( OnSubControlMouseDoubleClicked );
                 _dotControls[index].MouseEnter += new EventHandler( OnSubControlMouseEntered );
                 _dotControls[index].MouseHover += new EventHandler( OnSubControlMouseHovered );
                 _dotControls[index].MouseLeave += new EventHandler( OnSubControlMouseLeft );
                 _dotControls[index].MouseMove += new MouseEventHandler( OnSubControlMouseMoved );
  
                 Controls.Add( _dotControls[index] );
              }
           }
  
           SetStyle( ControlStyles.AllPaintingInWmPaint, true );
           SetStyle( ControlStyles.ContainerControl, true );
           SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
           SetStyle( ControlStyles.ResizeRedraw, true );
           SetStyle( ControlStyles.UserPaint, true );
  
           _referenceTextBox.AutoSize = true;
  
           Cursor = Cursors.IBeam;
  
           Size = MinimumSize;
  
           DragEnter += new DragEventHandler( IPAddressControl_DragEnter );
           DragDrop += new DragEventHandler( IPAddressControl_DragDrop );
        }
  
        #endregion // Constructors
  
        #region Protected Methods
  
        protected override void OnBackColorChanged( EventArgs e )
        {
           base.OnBackColorChanged( e );
           _backColorChanged = true;
        }
  
        protected override void OnFontChanged( EventArgs e )
        {
           base.OnFontChanged( e );
           AdjustSize();
        }
  
        protected override void OnGotFocus( EventArgs e )
        {
           base.OnGotFocus( e );
           _focused = true;
  
gt:          _fieldControls[0].TakeFocus( Direction.Forward, Selection.All );