첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

■ TextBox 클래스 : 영숫자/통화/날짜/정수/마스크/숫자 입력하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


Enumerations/ValidatingFlag.cs

 

 

using System;

using System.ComponentModel;

 

namespace TestProject

{

    /// <summary>

    /// 검증시 플래그

    /// </summary>

    [Flags]

    public enum ValidatingFlag

    {

        /// <summary>

        /// BEEP_IF_INVALID

        /// </summary>

        BEEP_IF_INVALID    = 0x00000001,

 

        /// <summary>

        /// BEEP_IF_EMPTY

        /// </summary>

        BEEP_IF_EMPTY = 0x00000002,

 

        /// <summary>

        /// BEEP

        /// </summary>

        BEEP = BEEP_IF_INVALID | BEEP_IF_EMPTY,

 

        /// <summary>

        /// SET_VALID_IF_INVALID

        /// </summary>

        SET_VALID_IF_INVALID = 0x00000004,

 

        /// <summary>

        /// SET_VALID_IF_EMPTY

        /// </summary>

        SET_VALID_IF_EMPTY = 0x00000008,

 

        /// <summary>

        /// SET_VALID

        /// </summary>

        SET_VALID = SET_VALID_IF_INVALID | SET_VALID_IF_EMPTY,

 

        /// <summary>

        /// SHOW_MESSAGE_IF_INVALID

        /// </summary>

        SHOW_MESSAGE_IF_INVALID = 0x00000010,

 

        /// <summary>

        /// SHOW_MESSAGE_IF_EMPTY

        /// </summary>

        SHOW_MESSAGE_IF_EMPTY = 0x00000020,

 

        /// <summary>

        /// SHOW_MESSAGE

        /// </summary>

        SHOW_MESSAGE = SHOW_MESSAGE_IF_INVALID | SHOW_MESSAGE_IF_EMPTY,

 

        /// <summary>

        /// SHOW_ICON_IF_INVALID

        /// </summary>

        SHOW_ICON_IF_INVALID = 0x00000040,

 

        /// <summary>

        /// SHOW_ICON_IF_EMPTY

        /// </summary>

        SHOW_ICON_IF_EMPTY = 0x00000080,

 

        /// <summary>

        /// SHOW_ICON

        /// </summary>

        SHOW_ICON = SHOW_ICON_IF_INVALID | SHOW_ICON_IF_EMPTY,

 

        /// <summary>

        /// MAXIMUM_IF_INVALID

        /// </summary>

        [EditorBrowsable(EditorBrowsableState.Never)]

        MAXIMUM_IF_INVALID = BEEP_IF_INVALID | SET_VALID_IF_INVALID | SHOW_MESSAGE_IF_INVALID | SHOW_ICON_IF_INVALID,

 

        /// <summary>

        /// MAXIMUM_IF_EMPTY

        /// </summary>

        [EditorBrowsable(EditorBrowsableState.Never)]

        MAXIMUM_IF_EMPTY = BEEP_IF_EMPTY | SET_VALID_IF_EMPTY | SHOW_MESSAGE_IF_EMPTY | SHOW_ICON_IF_EMPTY,

 

        /// <summary>

        /// MAXIMUM

        /// </summary>

        [EditorBrowsable(EditorBrowsableState.Never)]

        MAXIMUM = MAXIMUM_IF_INVALID + MAXIMUM_IF_EMPTY

    };

}

 

 

Selection.cs

 

 

using System;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 선택

    /// </summary>

    public class Selection

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Event

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 텍스트 변경전 이벤트 - TextChanging

 

        /// <summary>

        /// 텍스트 변경전 이벤트

        /// </summary>

        public event EventHandler TextChanging;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 텍스트 박스 베이스

        /// </summary>

        private TextBoxBase textBoxBase;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 텍스트 박스 - TextBox

 

        /// <summary>

        /// 텍스트 박스

        /// </summary>

        public TextBoxBase TextBox

        {

            get

            {

                return this.textBoxBase;

            }

        }

 

        #endregion

        #region 시작 인덱스 - StartIndex

 

        /// <summary>

        /// 시작 인덱스

        /// </summary>

        public int StartIndex

        {

            get

            {

                return this.textBoxBase.SelectionStart;

            }

            set

            {

                this.textBoxBase.SelectionStart = value;

            }

        }

 

        #endregion

        #region 종료 인덱스 - EndIndex

 

        /// <summary>

        /// 종료 인덱스

        /// </summary>

        public int EndIndex

        {

            get

            {

                return this.textBoxBase.SelectionStart + this.textBoxBase.SelectionLength;

            }

            set

            {

                this.textBoxBase.SelectionLength = value - this.textBoxBase.SelectionStart;

            }

        }

 

        #endregion

        #region 길이 - Length

 

        /// <summary>

        /// 길이

        /// </summary>

        public int Length

        {

            get

            {

                return this.textBoxBase.SelectionLength;

            }

            set

            {

                this.textBoxBase.SelectionLength = value;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Consturctor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - Selection(textBoxBase)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        public Selection(TextBoxBase textBoxBase)

        {

            this.textBoxBase = textBoxBase;

        }

 

        #endregion

        #region 생성자 - Selection(textBox, startIndex, endIndex)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        /// <param name="startIndex">시작 인덱스</param>

        /// <param name="endIndex">종료 인덱스</param>

        public Selection(TextBoxBase textBoxBase, int startIndex, int endIndex)

        {

            this.textBoxBase = textBoxBase;

 

            SetSelection(startIndex, endIndex);

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region + 연산자 재정의하기 - +(selection, offset)

 

        /// <summary>

        /// + 연산자 재정의하기

        /// </summary>

        /// <param name="selection">선택</param>

        /// <param name="offset">오프셋</param>

        /// <returns>선택</returns>

        public static Selection operator +(Selection selection, int offset)

        {

            return new Selection(selection.textBoxBase, selection.StartIndex + offset, selection.EndIndex + offset);

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 선택 설정하기 - SetSelection(startIndex, endIndex)

 

        /// <summary>

        /// 선택 설정하기

        /// </summary>

        /// <param name="startIndex">시작 인덱스</param>

        /// <param name="endIndex">종료 인덱스</param>

        public void SetSelection(int startIndex, int endIndex)

        {

            this.textBoxBase.SelectionStart  = startIndex;

            this.textBoxBase.SelectionLength = endIndex - startIndex;

        }

 

        #endregion

        #region 선택 구하기 - GetSelection(startIndex, endIndex)

 

        /// <summary>

        /// 선택 구하기

        /// </summary>

        /// <param name="startIndex">시작 인덱스</param>

        /// <param name="endIndex">종료 인덱스</param>

        public void GetSelection(out int startIndex, out int endIndex)

        {

            startIndex = this.textBoxBase.SelectionStart;

            endIndex   = startIndex + this.textBoxBase.SelectionLength;

 

            if(startIndex < 0)

            {

                startIndex = 0;

            }

 

            if(endIndex < startIndex)

            {

                endIndex = startIndex;

            }

        }

 

        #endregion

        #region 대체하기 - Replace(text)

 

        /// <summary>

        /// 대체하기

        /// </summary>

        /// <param name="text">텍스트</param>

        public void Replace(string text)

        {

            TextChanging?.Invoke(this, null);

 

            this.textBoxBase.SelectedText = text;

        }

 

        #endregion

        #region 선택 대체하기 - ReplaceSelection(startIndex, endIndex, text)

 

        /// <summary>

        /// 선택 대체하기

        /// </summary>

        /// <param name="startIndex">시작 인덱스</param>

        /// <param name="endIndex">종료 인덱스</param>

        /// <param name="text">텍스트</param>

        public void ReplaceSelection(int startIndex, int endIndex, string text)

        {

            SetSelection(startIndex, endIndex);

 

            Replace(text);

        }

 

        #endregion

        #region 이동하기 - MoveBy(startOffset, endOffset)

 

        /// <summary>

        /// 이동하기

        /// </summary>

        /// <param name="startOffset">시작 오프셋</param>

        /// <param name="endOffset">종료 오프셋</param>

        public void MoveBy(int startOffset, int endOffset)

        {

            EndIndex   += endOffset;

            StartIndex += startOffset;

        }

 

        #endregion

        #region 이동하기 - MoveBy(offset)

 

        /// <summary>

        /// 이동하기

        /// </summary>

        /// <param name="offset">오프셋</param>

        public void MoveBy(int offset)

        {

            MoveBy(offset, offset);

        }

 

        #endregion

    }

}

 

 

SelectionSaver.cs

 

 

using System;

using System.Diagnostics;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 선택 저장자

    /// </summary>

    public class SelectionSaver : IDisposable

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 텍스트 박스 베이스

        /// </summary>

        private TextBoxBase textBoxBase;

 

        /// <summary>

        /// 선택

        /// </summary>

        private Selection selection;

 

        /// <summary>

        /// 시작 인덱스

        /// </summary>

        private int startIndex;

        

        /// <summary>

        /// 종료 인덱스

        /// </summary>

        private int endIndex;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 텍스트 박스 - TextBox

 

        /// <summary>

        /// 텍스트 박스

        /// </summary>

        public TextBoxBase TextBox

        {

            get

            {

                return this.textBoxBase;

            }

        }

 

        #endregion

        #region 시작 인덱스 - StartIndex

 

        /// <summary>

        /// 시작 인덱스

        /// </summary>

        public int StartIndex

        {

            get

            {

                return this.startIndex;

            }

            set

            {

                this.startIndex = value;

            }

        }

 

        #endregion

        #region 종료 인덱스 - EndIndex

 

        /// <summary>

        /// 종료 인덱스

        /// </summary>

        public int EndIndex

        {

            get

            {

                return this.endIndex;

            }

            set

            {

                this.endIndex = value;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - SelectionSaver(textBoxBase)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        public SelectionSaver(TextBoxBase textBoxBase)

        {

            this.textBoxBase = textBoxBase;

 

            this.selection = new Selection(textBoxBase);

 

            this.selection.GetSelection(out this.startIndex, out this.endIndex);

        }

 

        #endregion

        #region 생성자 - SelectionSaver(textBoxBase, startIndex, endIndex)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        /// <param name="startIndex">시작 인덱스</param>

        /// <param name="endIndex">종료 인덱스</param>

        public SelectionSaver(TextBoxBase textBoxBase, int startIndex, int endIndex)

        {

            this.textBoxBase = textBoxBase;

 

            this.selection = new Selection(textBoxBase);

 

            Debug.Assert(startIndex <= endIndex);

 

            this.startIndex = startIndex;

            this.endIndex   = endIndex;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region + 연산자 재정의하기 - +(saver, offset)

 

        /// <summary>

        /// + 연산자 재정의하기

        /// </summary>

        /// <param name="saver">선택 저장자</param>

        /// <param name="offset">오프셋</param>

        /// <returns>선택 저장자</returns>

        public static SelectionSaver operator +(SelectionSaver saver, int offset)

        {

            return new SelectionSaver(saver.textBoxBase, saver.startIndex + offset, saver.endIndex + offset);

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 복구하기 - Restore()

 

        /// <summary>

        /// 복구하기

        /// </summary>

        public void Restore()

        {

            if(this.textBoxBase == null)

            {

                return;

            }

 

            this.selection.SetSelection(this.startIndex, this.endIndex);

 

            this.textBoxBase = null;

        }

 

        #endregion

        #region 이동하기 - MoveTo(startIndex, endIndex)

 

        /// <summary>

        /// 이동하기

        /// </summary>

        /// <param name="startIndex">시작 인덱스</param>

        /// <param name="endIndex">종료 인덱스</param>

        public void MoveTo(int startIndex, int endIndex)

        {

            Debug.Assert(startIndex <= endIndex);

 

            this.startIndex = startIndex;

            this.endIndex   = endIndex;

        }

 

        #endregion

        #region 이동하기 - MoveBy(startOffset, endOffset)

 

        /// <summary>

        /// 이동하기

        /// </summary>

        /// <param name="startOffset">시작 오프셋</param>

        /// <param name="endOffset">종료 오프셋</param>

        public void MoveBy(int startOffset, int endOffset)

        {

            this.startIndex += startOffset;

            this.endIndex   += endOffset;

 

            Debug.Assert(this.startIndex <= this.endIndex);

        }

 

        #endregion

        #region 이동하기 - MoveBy(offset)

 

        /// <summary>

        /// 이동하기

        /// </summary>

        /// <param name="offset">오프셋</param>

        public void MoveBy(int offset)

        {

            this.startIndex += offset;

            this.endIndex   += offset;

        }

 

        #endregion

        #region 갱신하기 - Update()

 

        /// <summary>

        /// 갱신하기

        /// </summary>

        public void Update()

        {

            if(this.textBoxBase != null)

            {

                this.selection.GetSelection(out this.startIndex, out this.endIndex);

            }

        }

 

        #endregion

        #region 비활성화하기 - Disable()

 

        /// <summary>

        /// 비활성화하기

        /// </summary>

        public void Disable()

        {

            this.textBoxBase = null;

        }

 

        #endregion

        #region 리소스 해제하기 - Dispose()

 

        /// <summary>

        /// 리소스 해제하기

        /// </summary>

        public void Dispose()

        {

            Restore();

        }

 

        #endregion

    }

}

 

 

Behaviors/Behavior.cs

 

 

using System;

using System.ComponentModel;

using System.Diagnostics;

using System.Runtime.InteropServices;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 동작

    /// </summary>

    public abstract class Behavior : IDisposable

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Import

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 메시지 비프 처리하기 - MessageBeep(messageBoxIcon)

 

        /// <summary>

        /// 메시지 비프 처리하기

        /// </summary>

        /// <param name="messageBoxIcon">메시지 박스 아이콘</param>

        /// <returns>처리 결과</returns>

        [DllImport("user32.dll")]

        protected static extern bool MessageBeep(MessageBoxIcon messageBoxIcon);

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 에러 제목

        /// </summary>

        private static string _errorCaption;

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Protected

 

        #region Field

 

        /// <summary>

        /// 텍스트 박스 베이스

        /// </summary>

        protected TextBoxBase textBoxBase;

 

        /// <summary>

        /// 플래그

        /// </summary>

        protected int flags;

 

        /// <summary>

        /// 텍스트 비변경 여부

        /// </summary>

        protected bool noTextChanged;

 

        /// <summary>

        /// 선택

        /// </summary>

        protected Selection selection;

 

        /// <summary>

        /// 에러 제공자

        /// </summary>

        protected ErrorProvider errorProvider;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 에러 제목 - ErrorCaption

 

        /// <summary>

        /// 에러 제목

        /// </summary>

        public static string ErrorCaption

        {

            get

            {

                if(_errorCaption == null)

                {

                    return Application.ProductName;

                }

 

                return _errorCaption;

            }

            set

            {

                _errorCaption = value;

            }

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 텍스트 박스 - TextBox

 

        /// <summary>

        /// 텍스트 박스

        /// </summary>

        public TextBoxBase TextBox

        {

            get

            {

                return this.textBoxBase;

            }

            set

            {

                if(value == null)

                {

                    throw new ArgumentNullException("value");

                }

 

                RemoveEventHandlers();

 

                this.textBoxBase = value;

 

                this.selection = new Selection(this.textBoxBase);

 

                this.selection.TextChanging += selection_TextChanging;

 

                AddEventHandlers();

            }

        }

 

        #endregion

        #region 플래그 - Flags

 

        /// <summary>

        /// 플래그

        /// </summary>

        public virtual int Flags

        {

            get

            {

                return this.flags;

            }

            set

            {

                if(this.flags == value)

                {

                    return;

                }

 

                this.flags = value;

 

                UpdateText();

            }

        }

 

        #endregion

        #region 에러 메시지 - ErrorMessage

 

        /// <summary>

        /// 에러 메시지

        /// </summary>

        public virtual string ErrorMessage

        {

            get

            {

                return "Please specify a valid value.";

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 생성자 - Behavior(textBoxBase, addEventHandlers)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        /// <param name="addEventHandlers">이벤트 핸들러 추가 여부</param>

        protected Behavior(TextBoxBase textBoxBase, bool addEventHandlers)

        {

            if(textBoxBase == null)

            {

                throw new ArgumentNullException("textBoxBase");

            }

 

            this.textBoxBase = textBoxBase;

 

            this.selection = new Selection(this.textBoxBase);

 

            this.selection.TextChanging += selection_TextChanging;

 

            if(addEventHandlers)

            {

                AddEventHandlers();

            }

        }

 

        #endregion

        #region 생성자 - Behavior(behavior)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="behavior">동작</param>

        protected Behavior(Behavior behavior)

        {

            if(behavior == null)

            {

                throw new ArgumentNullException("behavior");

            }

 

            TextBox = behavior.TextBox;

 

            this.flags = behavior.flags;

 

            behavior.Dispose();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 에러 아이콘 표시하기 - ShowErrorIcon(message)

 

        /// <summary>

        /// 에러 아이콘 표시하기

        /// </summary>

        /// <param name="message">메시지</param>

        public virtual void ShowErrorIcon(string message)

        {

            if(this.errorProvider == null)

            {

                if(message == string.Empty)

                {

                    return;

                }

 

                this.errorProvider = new ErrorProvider();

            }

 

            this.errorProvider.SetError(this.textBoxBase, message);

        }

 

        #endregion

        #region 에러 메시지 박스 표시하기 - ShowErrorMessageBox(message)

 

        /// <summary>

        /// 에러 메시지 박스 표시하기

        /// </summary>

        /// <param name="message">메시지</param>

        public virtual void ShowErrorMessageBox(string message)

        {

            MessageBox.Show(this.textBoxBase, message, ErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

        }

 

        #endregion

        #region 유효성 여부 구하기 - IsValid()

 

        /// <summary>

        /// 유효성 여부 구하기

        /// </summary>

        /// <returns>유효성 여부</returns>

        public virtual bool IsValid()

        {

            return true;

        }

 

        #endregion

        #region 검증하기 - Validate()

 

        /// <summary>

        /// 검증하기

        /// </summary>

        /// <returns>검증 결과</returns>

        public bool Validate()

        {

            return Validate(Flags, false);

        }

 

        #endregion

        #region 검증하기 - Validate(flags, setFocusIfNotValid)

 

        /// <summary>

        /// 검증하기

        /// </summary>

        /// <param name="flags">플래그</param>

        /// <param name="setFocusIfNotValid">무효시 포커스 설정 여부</param>

        /// <returns>검증 결과</returns>

        public virtual bool Validate(int flags, bool setFocusIfNotValid)

        {

            ShowErrorIcon(string.Empty);

 

            if((flags & (int)ValidatingFlag.MAXIMUM) == 0)

            {

                return true;

            }

 

            if((flags & (int)ValidatingFlag.MAXIMUM_IF_EMPTY) != 0 && this.textBoxBase.Text == string.Empty)

            {

                if((flags & (int)ValidatingFlag.BEEP_IF_EMPTY) != 0)

                {

                    MessageBeep(MessageBoxIcon.Exclamation);

                }

 

                if((flags & (int)ValidatingFlag.SET_VALID_IF_EMPTY) != 0)

                {

                    UpdateText();

 

                    return true;

                }

 

                if((flags & (int)ValidatingFlag.SHOW_ICON_IF_EMPTY) != 0)

                {

                    ShowErrorIcon(ErrorMessage);

                }

 

                if((flags & (int)ValidatingFlag.SHOW_MESSAGE_IF_EMPTY) != 0)

                {

                    ShowErrorMessageBox(ErrorMessage);

                }

 

                if(setFocusIfNotValid)

                {

                    this.textBoxBase.Focus();

                }

 

                return false;

            }

 

            if((flags & (int)ValidatingFlag.MAXIMUM_IF_INVALID) != 0 && this.textBoxBase.Text != string.Empty && !IsValid())

            {

                if((flags & (int)ValidatingFlag.BEEP_IF_INVALID) != 0)

                {

                    MessageBeep(MessageBoxIcon.Exclamation);

                }

 

                if((flags & (int)ValidatingFlag.SET_VALID_IF_INVALID) != 0)

                {

                    UpdateText();

 

                    return true;

                }

 

                if((flags & (int)ValidatingFlag.SHOW_ICON_IF_INVALID) != 0)

                {

                    ShowErrorIcon(ErrorMessage);

                }

 

                if((flags & (int)ValidatingFlag.SHOW_MESSAGE_IF_INVALID) != 0)

                {

                    ShowErrorMessageBox(ErrorMessage);

                }

 

                if(setFocusIfNotValid)

                {

                    this.textBoxBase.Focus();

                }

 

                return false;

            }

 

            return true;

        }

 

        #endregion

        #region 플래그 수정하기 - ModifyFlags(flags, added)

 

        /// <summary>

        /// 플래그 수정하기

        /// </summary>

        /// <param name="flags">플래그</param>

        /// <param name="added">추가 여부</param>

        public void ModifyFlags(int flags, bool added)

        {

            if(added)

            {

                Flags = this.flags | flags;

            }

            else

            {

                Flags = this.flags & ~flags;

            }

        }

 

        #endregion

        #region 플래그 존재 여부 구하기 - HasFlag(flag)

 

        /// <summary>

        /// 플래그 존재 여부 구하기

        /// </summary>

        /// <param name="flag">플래그</param>

        /// <returns>플래그 존재 여부</returns>

        public bool HasFlag(int flag)

        {

            return (this.flags & flag) != 0;

        }

 

        #endregion

        #region 텍스트 갱신하기 - UpdateText()

 

        /// <summary>

        /// 텍스트 갱신하기

        /// </summary>

        /// <returns>처리 결과</returns>

        public virtual bool UpdateText()

        {

            string validText = GetValidText();

 

            if(validText != this.textBoxBase.Text)

            {

                this.textBoxBase.Text = validText;

 

                return true;

            }

 

            return false;

        }

 

        #endregion

        #region 라인 추적하기 - TraceLine(message)

 

        /// <summary>

        /// 라인 추적하기

        /// </summary>

        /// <param name="message">메시지</param>

        [Conditional("TRACE_PROJECT")]

        public void TraceLine(string message)

        {

            Trace.WriteLine(message);

        }

 

        #endregion

        #region 리소스 해제하기 - Dispose()

 

        /// <summary>

        /// 리소스 해제하기

        /// </summary>

        public virtual void Dispose()

        {

            RemoveEventHandlers();

 

            this.textBoxBase = null;

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 바인딩 포맷시 처리하기 - binding_Format(sender, e)

 

        /// <summary>

        /// 바인딩 포맷시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected virtual void binding_Format(object sender, ConvertEventArgs e)

        {

        }

 

        #endregion

        #region 바인딩 파싱시 처리하기 - binding_Parse(sender, e)

 

        /// <summary>

        /// 바인딩 파싱시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected virtual void binding_Parse(object sender, ConvertEventArgs e)

        {

            if(e.Value.ToString() == string.Empty)

            {

                e.Value = DBNull.Value;

            }

        }

 

        #endregion

        #region 텍스트 박스 베이스 키 DOWN 처리하기 - textBoxBase_KeyDown(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 키 DOWN 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected virtual void textBoxBase_KeyDown(object sender, KeyEventArgs e)

        {

            TraceLine("Behavior.textBoxBase_KeyDown " + e.KeyCode);

 

            e.Handled = false;

        }

 

        #endregion

        #region 텍스트 박스 베이스 키 PRESS 처리하기 - textBoxBase_KeyPress(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 키 PRESS 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected virtual void textBoxBase_KeyPress(object sender, KeyPressEventArgs e)

        {

            TraceLine("Behavior.textBoxBase_KeyPress " + e.KeyChar);

 

            e.Handled = false;

        }

 

        #endregion

        #region 텍스트 박스 베이스 텍스트 변경시 처리하기 - textBoxBase_TextChanged(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 텍스트 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected virtual void textBoxBase_TextChanged(object sender, EventArgs e)

        {

            TraceLine("Behavior.textBoxBase_TextChanged " + this.noTextChanged);

 

            if(!this.noTextChanged)

            {

                UpdateText();

            }

 

            this.noTextChanged = false;

        }

 

        #endregion

        #region 텍스트 박스 베이스 검증시 처리하기 - textBoxBase_Validating(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 검증시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected virtual void textBoxBase_Validating(object sender, CancelEventArgs e)

        {

            TraceLine("Behavior.textBoxBase_Validating");

 

            e.Cancel = !Validate();

        }

 

        #endregion

        #region 텍스트 박스 베이스 포커스 상실시 처리하기 - textBoxBase_LostFocus(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 포커스 상실시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected virtual void textBoxBase_LostFocus(object sender, EventArgs e)

        {

            TraceLine("Behavior.textBoxBase_LostFocus");

        }

 

        #endregion

        #region 텍스트 박스 베이스 데이터 바인딩 컬렉션 변경시 처리하기 - textBoxBase_DataBindings_CollectionChanged(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 데이터 바인딩 컬렉션 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected virtual void textBoxBase_DataBindings_CollectionChanged(object sender, CollectionChangeEventArgs e)

        {

            if(e.Action == CollectionChangeAction.Add)

            {

                Binding binding = (Binding)e.Element;

 

                binding.Format += binding_Format;

                binding.Parse  += binding_Parse;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 이벤트 핸들러 추가하기 - AddEventHandlers()

 

        /// <summary>

        /// 이벤트 핸들러 추가하기

        /// </summary>

        protected virtual void AddEventHandlers()

        {

            this.textBoxBase.KeyDown                        += textBoxBase_KeyDown;

            this.textBoxBase.KeyPress                       += textBoxBase_KeyPress;

            this.textBoxBase.TextChanged                    += textBoxBase_TextChanged;

            this.textBoxBase.Validating                     += textBoxBase_Validating;

            this.textBoxBase.LostFocus                      += textBoxBase_LostFocus;

            this.textBoxBase.DataBindings.CollectionChanged += textBoxBase_DataBindings_CollectionChanged;

        }

 

        #endregion

        #region 이벤트 핸들러 제거하기 - RemoveEventHandlers()

 

        /// <summary>

        /// 이벤트 핸들러 제거하기

        /// </summary>

        protected virtual void RemoveEventHandlers()

        {

            if(this.textBoxBase == null)

            {

                return;

            }

 

            this.textBoxBase.KeyDown                        -= textBoxBase_KeyDown;

            this.textBoxBase.KeyPress                       -= textBoxBase_KeyPress;

            this.textBoxBase.TextChanged                    -= textBoxBase_TextChanged;

            this.textBoxBase.Validating                     -= textBoxBase_Validating;

            this.textBoxBase.LostFocus                      -= textBoxBase_LostFocus;

            this.textBoxBase.DataBindings.CollectionChanged -= textBoxBase_DataBindings_CollectionChanged;

        }

 

        #endregion

        #region 유효한 텍스트 구하기 - GetValidText()

 

        /// <summary>

        /// 유효한 텍스트 구하기

        /// </summary>

        /// <returns>유효한 텍스트</returns>

        protected virtual string GetValidText()

        {

            return this.textBoxBase.Text;

        }

 

        #endregion

        #region 정수 구하기 - ToInt(text)

 

        /// <summary>

        /// 정수 구하기

        /// </summary>

        /// <param name="text">텍스트</param>

        /// <returns>정수</returns>

        protected int ToInt(string text)

        {

            try

            {

                for(int i = 0, length = text.Length; i < length; i++)

                {

                    if(!Char.IsDigit(text[i]))

                    {

                        return Convert.ToInt32(text.Substring(0, i));

                    }

                }

 

                return Convert.ToInt32(text);

            }

            catch

            {

                return 0;

            }

        }

 

        #endregion

        #region 실수 구하기 - ToDouble(text)

 

        /// <summary>

        /// 실수 구하기

        /// </summary>

        /// <param name="text">텍스트</param>

        /// <returns>실수</returns>

        protected double ToDouble(string text)

        {

            try

            {

                return Convert.ToDouble(text);

            }

            catch

            {

                return 0;

            }

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 선택 텍스트 변경전 처리하기 - selection_TextChanging(sender, e)

 

        /// <summary>

        /// 선택 텍스트 변경전 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void selection_TextChanging(object sender, EventArgs e)

        {

            this.noTextChanged = true;

        }

 

        #endregion

    }

}

 

 

Behaviors/NumericBehavior.cs

 

 

using System;

using System.ComponentModel;

using System.Diagnostics;

using System.Globalization;

using System.Text;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 숫자 동작

    /// </summary>

    public class NumericBehavior : Behavior

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 플래그 - Flag

 

        /// <summary>

        /// 플래그

        /// </summary>

        [Flags]

        protected enum Flag

        {

            /// <summary>

            /// CAN_NOT_BE_NEGATIVE

            /// </summary>

            CAN_NOT_BE_NEGATIVE = 0x00010000,

 

            /// <summary>

            /// ADD_DECIMAL_AFTER_MAXIMUM_WHOLE_DIGITS

            /// </summary>

            ADD_DECIMAL_AFTER_MAXIMUM_WHOLE_DIGITS = 0x00020000

        };

 

        #endregion

        #region 포커스 상실시 플래그 - LostFocusFlag

 

        /// <summary>

        /// 포커스 상실시 플래그

        /// </summary>

        [Flags]

        public enum LostFocusFlag

        {

            /// <summary>

            /// PAD_WITH_ZEROS_BEFORE_DECIMAL

            /// </summary>

            PAD_WITH_ZEROS_BEFORE_DECIMAL = 0x00000100,

 

            /// <summary>

            /// PAD_WITH_ZEROS_AFTER_DECIMAL

            /// </summary>

            PAD_WITH_ZEROS_AFTER_DECIMAL = 0x00000200,

 

            /// <summary>

            /// DONT_PAD_WITH_ZEROS_IF_EMPTY

            /// </summary>

            DONT_PAD_WITH_ZEROS_IF_EMPTY = 0x00000400,

 

            /// <summary>

            /// REMOVE_EXTRA_LEADING_ZEROS

            /// </summary>

            REMOVE_EXTRA_LEADING_ZEROS = 0x00000800,

 

            /// <summary>

            /// MAXIMUM

            /// </summary>

            [EditorBrowsable(EditorBrowsableState.Never)]

            MAXIMUM = 0x00000F00,

 

            /// <summary>

            /// CALL_HANDLER_WHEN_TEXT_PROPERTY_IS_SET

            /// </summary>

            CALL_HANDLER_WHEN_TEXT_PROPERTY_IS_SET = 0x00001000,

 

            /// <summary>

            /// CALL_HANDLER_WHEN_TEXT_CHANGED

            /// </summary>

            CALL_HANDLER_WHEN_TEXT_CHANGED = 0x00002000

        };

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 최대 전체 숫자 카운트

        /// </summary>

        private int maximumWholeDigitCount = 9;

 

        /// <summary>

        /// 최대 소수점 이하 자리 카운트

        /// </summary>

        private int maximumDecimalPlaceCount = 4;

 

        /// <summary>

        /// 그룹 내 숫자 카운트

        /// </summary>

        private int digitCountInGroup = 0;

 

        /// <summary>

        /// 음수 기호

        /// </summary>

        private char negativeSign = NumberFormatInfo.CurrentInfo.NegativeSign[0];

 

        /// <summary>

        /// 소수점

        /// </summary>

        private char decimalPoint = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator[0];

 

        /// <summary>

        /// 그룹 분리자

        /// </summary>

        private char groupSeparator = NumberFormatInfo.CurrentInfo.NumberGroupSeparator[0];

 

        /// <summary>

        /// 접두사

        /// </summary>

        private string prefix = string.Empty;

 

        /// <summary>

        /// 범위 최소값

        /// </summary>

        private double rangeMinimumValue = double.MinValue;

 

        /// <summary>

        /// 범위 최대값

        /// </summary>

        private double rangeMaximumValue = double.MaxValue;

 

        /// <summary>

        /// 이전 분리자 카운트

        /// </summary>

        private int previousSeparatorCount = -1;

 

        /// <summary>

        /// 키 스트로크에 의한 텍스트 변경 여부

        /// </summary>

        private bool textChangedByKeystroke = false;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 에러 메시지 - ErrorMessage

 

        /// <summary>

        /// 에러 메시지

        /// </summary>

        public override string ErrorMessage

        {

            get

            {

                if(this.rangeMinimumValue > double.MinValue && this.rangeMaximumValue < double.MaxValue)

                {

                    return "Please specify a numeric value between " +

                           this.rangeMinimumValue.ToString()         +

                           " and "                                   +

                           this.rangeMaximumValue.ToString() + ".";

                }

                else if(this.rangeMinimumValue > double.MinValue)

                {

                    return "Please specify a numeric value greater than or equal to " + this.rangeMinimumValue.ToString() + ".";

                }

                else if(this.rangeMaximumValue < double.MinValue)

                {

                    return "Please specify a numeric value less than or equal to " + this.rangeMaximumValue.ToString() + ".";

                }

 

                return "Please specify a valid numeric value.";

            }

        }

 

        #endregion

        #region 최대 전체 숫자 카운트 - MaximumWholeDigitCount

 

        /// <summary>

        /// 최대 전체 숫자 카운트

        /// </summary>

        public int MaximumWholeDigitCount

        {

            get

            {

                return this.maximumWholeDigitCount;

            }

            set

            {

                if(this.maximumWholeDigitCount == value)

                {

                    return;

                }

 

                this.maximumWholeDigitCount = value;

 

                if(this.maximumWholeDigitCount < 1)

                {

                    this.maximumWholeDigitCount = 1;

                }

 

                UpdateText();

            }

        }

 

        #endregion

        #region 최대 소수점 이하 자리 카운트 - MaximumDecimalPlaceCount

 

        /// <summary>

        /// 최대 소수점 이하 자리 카운트

        /// </summary>

        public int MaximumDecimalPlaceCount

        {

            get

            {

                return this.maximumDecimalPlaceCount;

            }

            set

            {

                if(this.maximumDecimalPlaceCount == value)

                {

                    return;

                }

 

                this.maximumDecimalPlaceCount = value;

 

                if(this.maximumDecimalPlaceCount < 0)

                {

                    this.maximumDecimalPlaceCount = 0;

                }

 

                UpdateText();

            }

        }

 

        #endregion

        #region 음수 허용 여부 - AllowNegative

 

        /// <summary>

        /// 음수 허용 여부

        /// </summary>

        public bool AllowNegative

        {

            get

            {

                return !HasFlag((int)Flag.CAN_NOT_BE_NEGATIVE);

            }

            set

            {

                ModifyFlags((int)Flag.CAN_NOT_BE_NEGATIVE, !value);

            }

        }

 

        #endregion

        #region 최대 전체 숫자 카운트 설정 후 소수점 추가 여부 - AddDecimalAfterMaximumWholeDigitCount

 

        /// <summary>

        /// 최대 전체 숫자 카운트 설정 후 소수점 추가 여부

        /// </summary>

        public bool AddDecimalAfterMaximumWholeDigitCount

        {

            get

            {

                return HasFlag((int)Flag.ADD_DECIMAL_AFTER_MAXIMUM_WHOLE_DIGITS);

            }

            set

            {

                ModifyFlags((int)Flag.ADD_DECIMAL_AFTER_MAXIMUM_WHOLE_DIGITS, value);

            }

        }

 

        #endregion

        #region 그룹 내 숫자 카운트 - DigitCountInGroup

 

        /// <summary>

        /// 그룹 내 숫자 카운트

        /// </summary>

        public int DigitCountInGroup

        {

            get

            {

                return this.digitCountInGroup;

            }

            set

            {

                if(this.digitCountInGroup == value)

                {

                    return;

                }

 

                this.digitCountInGroup = value;

 

                if(this.digitCountInGroup < 0)

                {

                    this.digitCountInGroup = 0;

                }

 

                UpdateText();

            }

        }

 

        #endregion

        #region 소수점 - DecimalPoint

 

        /// <summary>

        /// 소수점

        /// </summary>

        public char DecimalPoint

        {

            get

            {

                return this.decimalPoint;

            }

            set

            {

                if(this.decimalPoint == value)

                {

                    return;

                }

 

                this.decimalPoint = value;

 

                AdjustDecimalAndGroupSeparators();

 

                UpdateText();

            }

        }

 

        #endregion

        #region 그룹 분리자 - GroupSeparator

 

        /// <summary>

        /// 그룹 분리자

        /// </summary>

        public char GroupSeparator

        {

            get

            {

                return this.groupSeparator;

            }

            set

            {

                if(this.groupSeparator == value)

                {

                    return;

                }

 

                this.groupSeparator = value;

 

                AdjustDecimalAndGroupSeparators();

 

                UpdateText();

            }

        }

 

        #endregion

        #region 음수 기호 - NegativeSign

 

        /// <summary>

        /// 음수 기호

        /// </summary>

        public char NegativeSign

        {

            get

            {

                return this.negativeSign;

            }

            set

            {

                if(this.negativeSign == value)

                {

                    return;

                }

 

                this.negativeSign = value;

 

                UpdateText();

            }

        }

 

        #endregion

        #region 접두사 - Prefix

 

        /// <summary>

        /// 접두사

        /// </summary>

        public String Prefix

        {

            get

            {

                return this.prefix;

            }

            set

            {

                if(this.prefix == value)

                {

                    return;

                }

 

                this.prefix = value;

 

                UpdateText();

            }

        }

 

        #endregion

        #region 범위 최소값 - RangeMinimumValue

 

        /// <summary>

        /// 범위 최소값

        /// </summary>

        public double RangeMinimumValue

        {

            get

            {

                return this.rangeMinimumValue;

            }

            set

            {

                this.rangeMinimumValue = value;

            }

        }

 

        #endregion

        #region 범위 최대값 - RangeMaximumValue

 

        /// <summary>

        /// 범위 최대값

        /// </summary>

        public double RangeMaximumValue

        {

            get

            {

                return this.rangeMaximumValue;

            }

            set

            {

                this.rangeMaximumValue = value;

            }

        }

 

        #endregion

        #region 마스크 - Mask

 

        /// <summary>

        /// 마스크

        /// </summary>

        public string Mask

        {

            get

            {

                StringBuilder stringBuilder = new StringBuilder();

 

                for(int i = 0; i < this.maximumWholeDigitCount; i++)

                {

                    stringBuilder.Append('0');

                }

 

                if(this.maximumDecimalPlaceCount > 0)

                {

                    stringBuilder.Append(this.decimalPoint);

                }

 

                for(int i = 0; i < this.maximumDecimalPlaceCount; i++)

                {

                    stringBuilder.Append('0');

                }

 

                stringBuilder = new StringBuilder(GetSeparatedText(stringBuilder.ToString()));

 

                for(int i = 0, length = stringBuilder.Length; i < length; i++)

                {

                    if(stringBuilder[i] == '0')

                    {

                        stringBuilder[i] = '#';

                    }

                }

 

                return stringBuilder.ToString();

            }

            set

            {

                int decimalPosition = -1;

                int length          = value.Length;

 

                this.maximumWholeDigitCount   = 0;

                this.maximumDecimalPlaceCount = 0;

                this.digitCountInGroup        = 0;

                this.flags                    = (this.flags & (int)~Flag.CAN_NOT_BE_NEGATIVE);

                this.prefix                   = string.Empty;

 

                for(int i = length - 1; i >= 0; i--)

                {

                    char character = value[i];

 

                    if(character == '#')

                    {

                        if(decimalPosition >= 0)

                        {

                            this.maximumWholeDigitCount++;

                        }

                        else

                        {

                            this.maximumDecimalPlaceCount++;

                        }

                    }

                    else if((character == '.' || character == this.decimalPoint) && decimalPosition < 0)

                    {

                        decimalPosition = i;

 

                        this.decimalPoint = character;

                    }

                    else if(character == ',' || character == this.groupSeparator)

                    {

                        if(this.digitCountInGroup == 0)

                        {

                            this.digitCountInGroup = (((decimalPosition >= 0) ? decimalPosition : length) - i) - 1;

                            this.groupSeparator    = character;

                        }

                    }

                    else

                    {

                        this.prefix = value.Substring(0, i + 1);

 

                        break;

                    }

                }

 

                if(decimalPosition < 0)

                {

                    this.maximumWholeDigitCount   = this.maximumDecimalPlaceCount;

                    this.maximumDecimalPlaceCount = 0;

                }

 

                Debug.Assert(this.maximumWholeDigitCount > 0);

 

                AdjustDecimalAndGroupSeparators();

 

                UpdateText();

            }

        }

 

        #endregion

        #region 숫자 텍스트 - NumericText

 

        /// <summary>

        /// 숫자 텍스트

        /// </summary>

        public string NumericText

        {

            get

            {

                return GetNumericText(this.textBoxBase.Text, false);

            }

        }

 

        #endregion

        #region 실제 숫자 텍스트 - RealNumericText

 

        /// <summary>

        /// 실제 숫자 텍스트

        /// </summary>

        public string RealNumericText

        {

            get

            {

                return GetNumericText(this.textBoxBase.Text, true);

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - NumericBehavior(textBoxBase)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        public NumericBehavior(TextBoxBase textBoxBase) : base(textBoxBase, true)

        {

            AdjustDecimalAndGroupSeparators();

        }

 

        #endregion

        #region 생성자 - NumericBehavior(textBoxBase, mask)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        /// <param name="mask">마스크</param>

        public NumericBehavior(TextBoxBase textBoxBase, string mask) : base(textBoxBase, true)

        {

            Mask = mask;

        }

 

        #endregion

        #region 생성자 - NumericBehavior(textBoxBase, maximumWholeDigitCount, maximumDecimalPlaceCount)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스</param>

        /// <param name="maximumWholeDigitCount">최대 전체 숫자 카운트</param>

        /// <param name="maximumDecimalPlaceCount">최대 소수점 자리 카운트</param>

        public NumericBehavior(TextBoxBase textBoxBase, int maximumWholeDigitCount, int maximumDecimalPlaceCount) : this(textBoxBase)

        {

            this.maximumWholeDigitCount   = maximumWholeDigitCount;

            this.maximumDecimalPlaceCount = maximumDecimalPlaceCount;

 

            if(this.maximumWholeDigitCount < 1)

            {

                this.maximumWholeDigitCount = 1;

            }

 

            if(this.maximumDecimalPlaceCount < 0)

            {

                this.maximumDecimalPlaceCount = 0;

            }

        }

 

        #endregion

        #region 생성자 - NumericBehavior(behavior)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="behavior">숫자 동작</param>

        public NumericBehavior(NumericBehavior behavior) : base(behavior)

        {

            this.maximumWholeDigitCount   = behavior.maximumWholeDigitCount;

            this.maximumDecimalPlaceCount = behavior.maximumDecimalPlaceCount;

            this.digitCountInGroup        = behavior.digitCountInGroup;

            this.negativeSign             = behavior.negativeSign;

            this.decimalPoint             = behavior.decimalPoint;

            this.groupSeparator           = behavior.groupSeparator;

            this.prefix                   = behavior.prefix;

            this.rangeMinimumValue        = behavior.rangeMinimumValue;

            this.rangeMaximumValue        = behavior.rangeMaximumValue;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 유효성 여부 구하기 - IsValid()

 

        /// <summary>

        /// 유효성 여부 구하기

        /// </summary>

        /// <returns>유효성 여부</returns>

        public override bool IsValid()

        {

            double value = ToDouble(RealNumericText);

 

            return (value >= this.rangeMinimumValue && value <= this.rangeMaximumValue);

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 바인딩 파싱시 처리하기 - binding_Parse(sender, e)

 

        /// <summary>

        /// 바인딩 파싱시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected override void binding_Parse(object sender, ConvertEventArgs e)

        {

            if(e.Value.ToString() == string.Empty)

            {

                e.Value = DBNull.Value;

            }

            else

            {

                e.Value = GetNumericText(e.Value.ToString(), false);

            }

        }

 

        #endregion

        #region 텍스트 박스 베이스 키 DOWN 처리하기 - textBoxBase_KeyDown(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 키 DOWN 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected override void textBoxBase_KeyDown(object sender, KeyEventArgs e)

        {

            TraceLine("NumericBehavior.textBoxBase_KeyDown " + e.KeyCode);

 

            if(e.KeyCode == Keys.Delete)

            {

                int startIndex;

                int endIndex;

 

                this.selection.GetSelection(out startIndex, out endIndex);

 

                string text  = this.textBoxBase.Text;

                int   length = text.Length;

 

                int prefixLength = this.prefix.Length;

 

                if(startIndex < prefixLength && length > prefixLength)

                {

                    if(endIndex != length)

                    {

                        e.Handled = true;

                    }

                    return;

                }

 

                this.textChangedByKeystroke = true;

 

                if(startIndex < length && text[startIndex] == this.groupSeparator && startIndex == endIndex)

                {

                    SendKeys.SendWait("{RIGHT}");

                }

 

                this.previousSeparatorCount = GetGroupSeparatorCount(text);

 

                if(endIndex == length)

                {

                    SendKeys.Send("{RIGHT}");

                }

            }

        }

 

        #endregion

        #region 텍스트 박스 베이스 키 PRESS 처리하기 - textBoxBase_KeyPress(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 키 PRESS 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected override void textBoxBase_KeyPress(object sender, KeyPressEventArgs e)

        {

            TraceLine("NumericBehavior.textBoxBase_KeyPress " + e.KeyChar);

 

            if(this.textBoxBase.ReadOnly)

            {

                return;

            }

 

            char character = e.KeyChar;

 

            e.Handled = true;

 

            this.textChangedByKeystroke = true;

 

            int startIndex;

            int endIndex;

 

            this.selection.GetSelection(out startIndex, out endIndex);

 

            string text = this.textBoxBase.Text;

 

            this.previousSeparatorCount = -1;

 

            string numericText            = NumericText;

            int    decimalPosition        = text.IndexOf(this.decimalPoint);

            int    numericDecimalPosition = numericText.IndexOf(this.decimalPoint);

            int    length                 = text.Length;

            int    numericLength          = numericText.Length;

            int    prefixLength           = this.prefix.Length;

            int    separatorCount         = GetGroupSeparatorCount(text);

 

            if(startIndex < prefixLength && !Char.IsControl(character))

            {

                char prefixCharacter = this.prefix[startIndex];

 

                if(prefixCharacter == character)

                {

                    if(length > startIndex)

                    {

                        endIndex = (endIndex == length ? endIndex : (startIndex + 1));

 

                        this.selection.ReplaceSelection(startIndex, endIndex, character.ToString());

                    }

                    else

                    {

                        base.textBoxBase_KeyPress(sender, e);

                    }

                }

                else if(Char.IsDigit(character) || character == this.negativeSign || character == this.decimalPoint)

                {

                    endIndex = (endIndex == length ? endIndex : prefixLength);

 

                    this.selection.ReplaceSelection(startIndex, endIndex, this.prefix.Substring(startIndex));

 

                    textBoxBase_KeyPress(sender, e);

                }

 

                return;

            }

 

            if(character == this.negativeSign && AllowNegative)

            {

                if(startIndex == prefixLength)

                {

                    if(numericText != string.Empty && numericText[0] == this.negativeSign)

                    {

                        endIndex = (endIndex == length ? endIndex : (startIndex + 1));

 

                        this.selection.ReplaceSelection(startIndex, endIndex, this.negativeSign.ToString());

 

                        return;

                    }

                }

                else

                {

                    if(numericText[0] == this.negativeSign)

                    {

                        this.selection.ReplaceSelection(prefixLength, prefixLength + 1, string.Empty);

 

                        this.selection.SetSelection(startIndex - 1, endIndex - 1);

                    }

                    else

                    {

                        this.selection.ReplaceSelection(prefixLength, prefixLength, this.negativeSign.ToString());

 

                        this.selection.SetSelection(startIndex + 1, endIndex + 1);

                    }

 

                    return;

                }

            }

            else if(character == this.decimalPoint && this.maximumDecimalPlaceCount > 0)

            {

                if(decimalPosition >= 0)

                {

                    if(decimalPosition >= startIndex && decimalPosition < endIndex)

                    {

                        this.previousSeparatorCount = separatorCount;

                    }

                    else

                    {

                        this.selection.SetSelection(decimalPosition + 1, decimalPosition + 1);

 

                        return;

                    }

                }

                else

                {

                    this.previousSeparatorCount = separatorCount;

                }

            }

            else if(Char.IsDigit(character))

            {

                if(decimalPosition >= 0 && decimalPosition < startIndex)

                {

                    if(numericText.Substring(numericDecimalPosition + 1).Length == this.maximumDecimalPlaceCount)

                    {

                        if(startIndex <= decimalPosition + this.maximumDecimalPlaceCount)

                        {

                            endIndex = (endIndex == length ? endIndex : (startIndex + 1));

 

                            this.selection.ReplaceSelection(startIndex, endIndex, character.ToString());

                        }

 

                        return;

                    }

                }

                else

                {

                    bool isNegative = (numericText.Length != 0 && numericText[0] == this.negativeSign);

 

                    if(startIndex == this.maximumWholeDigitCount + separatorCount + prefixLength + (isNegative ? 1 : 0))

                    {

                        if(AddDecimalAfterMaximumWholeDigitCount && this.maximumDecimalPlaceCount > 0)

                        {

                            endIndex = (endIndex == length ? endIndex : (startIndex + 2));

 

                            this.selection.ReplaceSelection(startIndex, endIndex, this.decimalPoint.ToString() + character);

                        }

 

                        return;

                    }

 

                    if

                    (

                        numericText.Substring

                        (

                            0,

                            numericDecimalPosition >= 0 ? numericDecimalPosition : numericLength

                        ).Length == this.maximumWholeDigitCount + (isNegative ? 1 : 0)

                    )

                    {

                        if(text[startIndex] == this.groupSeparator)

                        {

                            startIndex++;

                        }

 

                        endIndex = (endIndex == length ? endIndex : (startIndex + 1));

 

                        this.selection.ReplaceSelection(startIndex, endIndex, character.ToString());

 

                        return;

                    }

 

                    this.previousSeparatorCount = separatorCount;

                }

            }

            else if(Char.IsControl(character))

            {

                this.previousSeparatorCount = separatorCount;

            }

            else

            {

                return;

            }

 

            base.textBoxBase_KeyPress(sender, e);

        }

 

        #endregion

        #region 텍스트 박스 베이스 텍스트 변경시 처리하기 - textBoxBase_TextChanged(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 텍스트 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected override void textBoxBase_TextChanged(object sender, EventArgs e)

        {

            TraceLine("NumericBehavior.textBoxBase_TextChanged");

 

            SelectionSaver selectionSaver = new SelectionSaver(this.textBoxBase);

 

            bool textChangedByKeystroke = this.textChangedByKeystroke;

 

            base.textBoxBase_TextChanged(sender, e);

 

            if(this.previousSeparatorCount >= 0)

            {

                using(selectionSaver)

                {

                    int newSeparatorCount = GetGroupSeparatorCount(this.textBoxBase.Text);

 

                    if(this.previousSeparatorCount != newSeparatorCount && selectionSaver.StartIndex > this.prefix.Length)

                    {

                        selectionSaver.MoveBy(newSeparatorCount - this.previousSeparatorCount);

                    }

                }

            }

 

            if

            (

                HasFlag((int)LostFocusFlag.CALL_HANDLER_WHEN_TEXT_CHANGED) ||

                (!textChangedByKeystroke && HasFlag((int)LostFocusFlag.CALL_HANDLER_WHEN_TEXT_PROPERTY_IS_SET))

            )

            {

                textBoxBase_LostFocus(sender, e);

            }

 

            this.textChangedByKeystroke = false;

        }

 

        #endregion

        #region 텍스트 박스 베이스 포커스 상실시 처리하기 - textBoxBase_LostFocus(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 포커스 상실시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected override void textBoxBase_LostFocus(object sender, EventArgs e)

        {

            TraceLine("NumericBehavior.textBoxBase_LostFocus");

 

            if(!HasFlag((int)LostFocusFlag.MAXIMUM))

            {

                return;

            }

 

            string originalText = GetNumericText(this.textBoxBase.Text, true);

            string text         = originalText;

            int    length       = text.Length;

 

            if(HasFlag((int)LostFocusFlag.REMOVE_EXTRA_LEADING_ZEROS) && length > 0)

            {

                bool isNegative = (text[0] == this.negativeSign);

 

                if(isNegative)

                {

                    text = text.Substring(1);

                }

 

                text = text.TrimStart('0');

 

                if(text == string.Empty || text[0] == this.decimalPoint)

                {

                    text = '0' + text;

                }

 

                if(isNegative)

                {

                    text = this.negativeSign + text;

                }

            }

            else if(length == 0 && HasFlag((int)LostFocusFlag.DONT_PAD_WITH_ZEROS_IF_EMPTY))

            {

                return;

            }

 

            int decimalPosition          = text.IndexOf('.');

            int maximumDecimalPlaceCount = this.maximumDecimalPlaceCount;

            int maximuWholeDigitCount    = this.maximumWholeDigitCount;

 

            if(HasFlag((int)LostFocusFlag.PAD_WITH_ZEROS_AFTER_DECIMAL) && maximumDecimalPlaceCount > 0)

            {

                if(decimalPosition < 0)

                {

                    if(length == 0 || text == "-")

                    {

                        text   = "0";

                        length = 1;

                    }

 

                    text += '.';

 

                    decimalPosition = length++;

                }

 

                text = InsertZeros(text, -1, maximumDecimalPlaceCount - (length - decimalPosition - 1));

            }

 

            if(HasFlag((int)LostFocusFlag.PAD_WITH_ZEROS_BEFORE_DECIMAL) && maximuWholeDigitCount > 0)

            {

                if(decimalPosition < 0)

                {

                    decimalPosition = length;

                }

 

                if(length > 0 && text[0] == '-')

                {

                    decimalPosition--;

                }

 

                text = InsertZeros(text, (length > 0 ? (text[0] == '-' ? 1 : 0) : -1), maximuWholeDigitCount - decimalPosition);

            }

 

            if(text != originalText)

            {

                if(decimalPosition >= 0 && this.decimalPoint != '.')

                {

                    text = text.Replace('.', this.decimalPoint);

                }

 

                using(SelectionSaver selectionSaver = new SelectionSaver(this.textBoxBase))

                {

                    this.textBoxBase.Text = text;

                }

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

        

        #region 십진수 및 그룹 분리자 조정하기 - AdjustDecimalAndGroupSeparators()

 

        /// <summary>

        /// 십진수 및 그룹 분리자 조정하기

        /// </summary>

        protected void AdjustDecimalAndGroupSeparators()

        {

            if(this.decimalPoint == this.groupSeparator)

            {

                this.groupSeparator = (this.decimalPoint == ',' ? '.' : ',');

            }

        }

 

        #endregion

        #region 0 삽입하기 - InsertZeros(text, startIndex, count)

 

        /// <summary>

        /// 0 삽입하기

        /// </summary>

        /// <param name="text">텍스트</param>

        /// <param name="startIndex">숫자 인덱스</param>

        /// <param name="count">카운트</param>

        /// <returns>처리 결과</returns>

        protected string InsertZeros(string text, int startIndex, int count)

        {

            if(startIndex < 0 && count > 0)

            {

                startIndex = text.Length;

            }

 

            StringBuilder stringBuilder = new StringBuilder(text);

 

            for(int i = 0; i < count; i++)

            {

                stringBuilder.Insert(startIndex, '0');

            }

 

            return stringBuilder.ToString();

        }

 

        #endregion

        #region 범위 내 조정하기 - AdjustWithinRange()

 

        /// <summary>

        /// 범위 내 조정하기

        /// </summary>

        protected void AdjustWithinRange()

        {

            if(IsValid())

            {

                return;

            }

 

            if(this.textBoxBase.Text == string.Empty)

            {

                this.textBoxBase.Text = " ";

            }

            else

            {

                UpdateText();

            }

 

            double value = ToDouble(RealNumericText);

 

            if(value < this.rangeMinimumValue)

            {

                this.textBoxBase.Text = this.rangeMinimumValue.ToString();

            }

            else if(value > this.rangeMaximumValue)

            {

                this.textBoxBase.Text = this.rangeMaximumValue.ToString();

            }

        }

 

        #endregion

        #region 숫자 텍스트 구하기 - GetNumericText(text, realNumeric)

 

        /// <summary>

        /// 숫자 텍스트 구하기

        /// </summary>

        /// <param name="text">텍스트</param>

        /// <param name="realNumeric">실제 숫자 여부</param>

        /// <returns>숫자 텍스트</returns>

        protected string GetNumericText(string text, bool realNumeric)

        {

            StringBuilder stringBuilder = new StringBuilder();

 

            bool isNegative      = false;

            bool hasDecimalPoint = false;

 

            foreach(char character in text)

            {

                if(Char.IsDigit(character))

                {

                    stringBuilder.Append(character);

                }

                else if(character == this.negativeSign)

                {

                    isNegative = true;

                }

                else if(character == this.decimalPoint && !hasDecimalPoint)

                {

                    hasDecimalPoint = true;

 

                    stringBuilder.Append(realNumeric ? '.' : this.decimalPoint);

                }

            }

 

            if(isNegative)

            {

                stringBuilder.Insert(0, realNumeric ? '-' : this.negativeSign);

            }

 

            return stringBuilder.ToString();

        }

 

        #endregion

        #region 분리된 텍스트 구하기 - GetSeparatedText(text)

 

        /// <summary>

        /// 분리된 텍스트 구하기

        /// </summary>

        /// <param name="text">텍스트</param>

        /// <returns>분리된 텍스트</returns>

        protected string GetSeparatedText(string text)

        {

            string numericText   = GetNumericText(text, false);

            string separatedText = numericText;

 

            int decimalPosition = numericText.IndexOf(this.decimalPoint);

 

            if(decimalPosition >= 0)

            {

                separatedText = separatedText.Substring(0, decimalPosition);

            }

 

            if(this.digitCountInGroup > 0)

            {

                int length = separatedText.Length;

 

                bool isNegative = (separatedText != string.Empty && separatedText[0] == this.negativeSign);

 

                for(int i = length - (this.digitCountInGroup + 1); i >= (isNegative ? 1 : 0); i -= this.digitCountInGroup)

                {

                    separatedText = separatedText.Substring(0, i + 1) + this.groupSeparator + separatedText.Substring(i + 1);

                }

            }

 

            if(separatedText != string.Empty || decimalPosition >= 0)

            {

                separatedText = this.prefix + separatedText;

 

                if(decimalPosition >= 0)

                {

                    separatedText += numericText.Substring(decimalPosition);

                }

            }

 

            return separatedText;

        }

 

        #endregion

        #region 유효한 텍스트 구하기 - GetValidText()

 

        /// <summary>

        /// 유효한 텍스트 구하기

        /// </summary>

        /// <returns>유효한 텍스트</returns>

        protected override string GetValidText()

        {

            string text         = this.textBoxBase.Text;

            bool   isNegative   = false;

            int    prefixLength = this.prefix.Length;

 

            StringBuilder stringBuilder = new StringBuilder();

 

            for(int i = 0, decimalPosition = -1, newLength = 0, length = text.Length; i < length; i++)

            {

                char character = text[i];

 

                if(character == this.negativeSign && AllowNegative)

                {

                    isNegative = true;

                }

 

                else if(Char.IsDigit(character))

                {

                    if(decimalPosition < 0 && newLength == this.maximumWholeDigitCount)

                    {

                        continue;

                    }

 

                    if(decimalPosition >= 0 && newLength > decimalPosition + this.maximumDecimalPlaceCount)

                    {

                        break;

                    }

 

                    stringBuilder.Append(character);

 

                    newLength++;

                }

                else if(character == this.decimalPoint && decimalPosition < 0)

                {

                    if(this.maximumDecimalPlaceCount == 0)

                    {

                        break;

                    }

 

                    stringBuilder.Append(character);

 

                    decimalPosition = newLength;

 

                    newLength++;

                }

            }

 

            if(isNegative)

            {

                stringBuilder.Insert(0, this.negativeSign);

            }

 

            return GetSeparatedText(stringBuilder.ToString());

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 그룹 분리자 수 구하기 - GetGroupSeparatorCount(text)

 

        /// <summary>

        /// 그룹 분리자 수 구하기

        /// </summary>

        /// <param name="text">텍스트</param>

        /// <returns>그룹 분리자 수</returns>

        private int GetGroupSeparatorCount(string text)

        {

            int count = 0;

 

            foreach(char character in text)

            {

                if(character == this.groupSeparator)

                {

                    count++;

                }

            }

 

            return count;

        }

 

        #endregion

    }

}

 

 

Behaviors/IntegerBehavior.cs

 

 

using System;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 정수 동작

    /// </summary>

    public class IntegerBehavior : NumericBehavior

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 최대 소수점 자리 카운트 - MaximumDecimalPlaceCount

 

        /// <summary>

        /// 최대 소수점 자리 카운트

        /// </summary>

        public new int MaximumDecimalPlaceCount

        {

            get

            {

                return base.MaximumDecimalPlaceCount;

            }

        }

 

        #endregion

        #region 마스크 - Mask

 

        /// <summary>

        /// 마스크

        /// </summary>

        public new string Mask

        {

            get

            {

                return base.Mask;

            }

            set

            {

                base.Mask = value;

 

                if(base.MaximumDecimalPlaceCount > 0)

                {

                    base.MaximumDecimalPlaceCount = 0;

                }

            }

        }

        

        #endregion

        

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - IntegerBehavior(textBoxBase)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        public IntegerBehavior(TextBoxBase textBoxBase) : base(textBoxBase, 9, 0)

        {

            SetDefaultRange();

        }

 

        #endregion

        #region 생성자 - IntegerBehavior(textBoxBase, maximumWholeDigitCount)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        /// <param name="maximumWholeDigitCount">최대 전체 숫자 카운트</param>

        public IntegerBehavior(TextBoxBase textBoxBase, int maximumWholeDigitCount) : base(textBoxBase, maximumWholeDigitCount, 0)

        {

            SetDefaultRange();

        }

 

        #endregion

        #region 생성자 - IntegerBehavior(behavior)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="behavior">정수 동작</param>

        public IntegerBehavior(IntegerBehavior behavior) : base(behavior)

        {

            SetDefaultRange();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region 디폴트 범위 설정하기 - SetDefaultRange()

 

        /// <summary>

        /// 디폴트 범위 설정하기

        /// </summary>

        private void SetDefaultRange()

        {

            RangeMinimumValue = Int32.MinValue;

            RangeMaximumValue = Int32.MaxValue;

        }

 

        #endregion

    }

}

 

 

Behaviors/CurrencyBehavior.cs

 

 

using System.Globalization;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 통화 동작

    /// </summary>

    public class CurrencyBehavior : NumericBehavior

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - CurrencyBehavior(textBoxBase)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        public CurrencyBehavior(TextBoxBase textBoxBase) : base(textBoxBase)

        {

            this.flags |=

            (

                (int)LostFocusFlag.REMOVE_EXTRA_LEADING_ZEROS   |

                (int)LostFocusFlag.PAD_WITH_ZEROS_AFTER_DECIMAL |

                (int)LostFocusFlag.DONT_PAD_WITH_ZEROS_IF_EMPTY |

                (int)LostFocusFlag.CALL_HANDLER_WHEN_TEXT_PROPERTY_IS_SET

            );

 

            DigitCountInGroup        = NumberFormatInfo.CurrentInfo.CurrencyGroupSizes[0];

            MaximumDecimalPlaceCount = NumberFormatInfo.CurrentInfo.CurrencyDecimalDigits;

            DecimalPoint             = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator[0];

            GroupSeparator           = NumberFormatInfo.CurrentInfo.CurrencyGroupSeparator[0];

 

            switch(NumberFormatInfo.CurrentInfo.CurrencyPositivePattern)

            {

                case 0 : Prefix = NumberFormatInfo.CurrentInfo.CurrencySymbol;       break;

                case 2 : Prefix = NumberFormatInfo.CurrentInfo.CurrencySymbol + ' '; break;

            }

 

            AdjustDecimalAndGroupSeparators();

        }

 

        #endregion

        #region 생성자 - CurrencyBehavior(behavior)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="behavior">통화 동작</param>

        public CurrencyBehavior(CurrencyBehavior behavior) : base(behavior)

        {

        }

 

        #endregion

    }

}

 

 

Behaviors/AlphanumericBehavior.cs

 

 

using System;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 영숫자 동작

    /// </summary>

    public class AlphanumericBehavior : Behavior

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 무효한 문자 배열

        /// </summary>

        private char[] invalidCharacterArray = { '%', '\'', '*', '"', '+', '?', '>', '<', ':', '\\' };

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 무효한 문자 배열 - InvalidCharacterArray

 

        /// <summary>

        /// 무효한 문자 배열

        /// </summary>

        public char[] InvalidCharacterArray

        {

            get

            {

                return this.invalidCharacterArray;

            }

            set

            {

                if(this.invalidCharacterArray == value)

                {

                    return;

                }

 

                this.invalidCharacterArray = value;

 

                UpdateText();

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - AlphanumericBehavior(textBoxBase)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        public AlphanumericBehavior(TextBoxBase textBoxBase) : base(textBoxBase, true)

        {

        }

 

        #endregion

        #region 생성자 - AlphanumericBehavior(textBoxBase, invalidCharacterArray)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        /// <param name="invalidCharacterArray">무효한 문자 배열</param>

        public AlphanumericBehavior(TextBoxBase textBoxBase, char[] invalidCharacterArray) : base(textBoxBase, true)

        {

            this.invalidCharacterArray = invalidCharacterArray;

        }

 

        #endregion

        #region 생성자 - AlphanumericBehavior(textBoxBase, invalidCharacterArray)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        /// <param name="invalidCharacterArray">무효한 문자 배열</param>

        public AlphanumericBehavior(TextBoxBase textBoxBase, string invalidCharacterArray) : base(textBoxBase, true)

        {

            this.invalidCharacterArray = invalidCharacterArray.ToCharArray();

        }

 

        #endregion

        #region 생성자 - AlphanumericBehavior(behavior)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="behavior">영숫자 동작</param>

        public AlphanumericBehavior(AlphanumericBehavior behavior) : base(behavior)

        {

            this.invalidCharacterArray = behavior.invalidCharacterArray;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 유효한 텍스트 구하기 - GetValidText()

 

        /// <summary>

        /// 유효한 텍스트 구하기

        /// </summary>

        /// <returns>유효한 텍스트</returns>

        protected override string GetValidText()

        {

            string text = this.textBoxBase.Text;

 

            if(this.invalidCharacterArray != null && text.IndexOfAny(this.invalidCharacterArray) >= 0)

            {

                foreach(char character in this.invalidCharacterArray)

                {

                    if(text.IndexOf(character) >= 0)

                    {

                        text = text.Replace(character.ToString(), string.Empty);

                    }

                }

            }

 

            if(text.Length > this.textBoxBase.MaxLength)

            {

                text = text.Remove(this.textBoxBase.MaxLength, text.Length - this.textBoxBase.MaxLength);

            }

 

            return text;

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 텍스트 박스 베이스 키 PRESS 처리하기 - textBoxBase_KeyPress(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 키 PRESS 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected override void textBoxBase_KeyPress(object sender, KeyPressEventArgs e)

        {

            TraceLine("AlphanumericBehavior.textBoxBase_KeyPress " + e.KeyChar);

 

            if(this.textBoxBase.ReadOnly || this.invalidCharacterArray == null)

            {

                return;

            }

 

            char character = e.KeyChar;

 

            e.Handled = true;

 

            if(Array.IndexOf(this.invalidCharacterArray, character) >= 0)

            {

                MessageBeep(MessageBoxIcon.Exclamation);

 

                return;

            }

 

            string text = this.textBoxBase.Text;

 

            if(text.Length == this.textBoxBase.MaxLength && this.textBoxBase.MaxLength > 0 && !Char.IsControl(character))

            {

                int startIndex;

                int endIndex;

 

                this.selection.GetSelection(out startIndex, out endIndex);

 

                if(startIndex < this.textBoxBase.MaxLength)

                {

                    this.selection.ReplaceSelection(startIndex, startIndex + 1, character.ToString());

                }

 

                return;

            }

 

            base.textBoxBase_KeyPress(sender, e);

        }

 

        #endregion

    }

}

 

 

Behaviors/MaskedBehavior.cs

 

 

using System.Collections;

using System.Text;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 마스크 동작

    /// </summary>

    public class MaskedBehavior : Behavior

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Class

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 상징 - Symbol

 

        /// <summary>

        /// 상징

        /// </summary>

        public class Symbol

        {

            //////////////////////////////////////////////////////////////////////////////////////////////////// Delegate

            ////////////////////////////////////////////////////////////////////////////////////////// Public

 

            #region 검증자 메소드 - ValidatorMethod(character)

 

            /// <summary>

            /// 검증자 메소드

            /// </summary>

            /// <param name="character">문자</param>

            /// <returns>검증 결과</returns>

            public delegate bool ValidatorMethod(char character);

 

            #endregion

            #region 포매터 메소드 - FormatterMethod(character)

 

            /// <summary>

            /// 포매터 메소드

            /// </summary>

            /// <param name="character">문자</param>

            /// <returns>문자</returns>

            public delegate char FormatterMethod(char character);

 

            #endregion

 

            //////////////////////////////////////////////////////////////////////////////////////////////////// Event

            ////////////////////////////////////////////////////////////////////////////////////////// Public

 

            #region 검증자 이벤트 - Validator

 

            /// <summary>

            /// 검증자 이벤트

            /// </summary>

            public event ValidatorMethod Validator;

 

            #endregion

            #region 포매터 이벤트 - Formatter

 

            /// <summary>

            /// 포매터 이벤트

            /// </summary>

            public event FormatterMethod Formatter;

 

            #endregion

 

            //////////////////////////////////////////////////////////////////////////////////////////////////// Field

            ////////////////////////////////////////////////////////////////////////////////////////// Private

 

            #region Field

 

            /// <summary>

            /// 상징

            /// </summary>

            private char symbol;

 

            #endregion

 

            //////////////////////////////////////////////////////////////////////////////////////////////////// Property

            ////////////////////////////////////////////////////////////////////////////////////////// Public

 

            #region 문자 - Character

 

            /// <summary>

            /// 문자

            /// </summary>

            public char Character

            {

                get

                {

                    return this.symbol;

                }

                set

                {

                    this.symbol = value;

                }

            }

 

            #endregion

 

            //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

            ////////////////////////////////////////////////////////////////////////////////////////// Public

 

            #region 생성자 - Symbol(symbol, validator, formatter)

 

            /// <summary>

            /// 생성자

            /// </summary>

            /// <param name="symbol">상징</param>

            /// <param name="validator">검증자</param>

            /// <param name="formatter">포매터</param>

            public Symbol(char symbol, ValidatorMethod validator, FormatterMethod formatter)

            {

                this.symbol = symbol;

 

                Validator = validator;

                Formatter = formatter;

            }

 

            #endregion

            #region 생성자 - Symbol(symbol)

 

            /// <summary>

            /// 생성자

            /// </summary>

            /// <param name="symbol">상징</param>

            public Symbol(char symbol) : this(symbol, null, null)

            {

            }

 

            #endregion

            #region 생성자 - Symbol(symbol, validator)

 

            /// <summary>

            /// 생성자

            /// </summary>

            /// <param name="symbol">상징</param>

            /// <param name="validator">검증자</param>

            public Symbol(char symbol, ValidatorMethod validator) : this(symbol, validator, null)

            {

            }

 

            #endregion

 

            //////////////////////////////////////////////////////////////////////////////////////////////////// Method

            ////////////////////////////////////////////////////////////////////////////////////////// Static

            //////////////////////////////////////////////////////////////////////////////// Public

 

            #region 암시적 변환하기 - char(symbol)

 

            /// <summary>

            /// 암시적 변환하기

            /// </summary>

            /// <param name="symbol">상징</param>

            public static implicit operator char(Symbol symbol)

            {

                return symbol.Character;

            }

 

            #endregion

 

            ////////////////////////////////////////////////////////////////////////////////////////// Instance

            //////////////////////////////////////////////////////////////////////////////// Public

 

            #region 검증하기 - Validate(character)

 

            /// <summary>

            /// 검증하기

            /// </summary>

            /// <param name="character">문자</param>

            /// <returns>검증 결과</returns>

            public virtual bool Validate(char character)

            {

                if(Validator != null)

                {

                    foreach(ValidatorMethod validator in Validator.GetInvocationList())

                    {

                        if(!validator(character))

                        {

                            return false;

                        }

                    }

                }

 

                return true;

            }

 

            #endregion

            #region 포맷하기 - Format(character)

 

            /// <summary>

            /// 포맷하기

            /// </summary>

            /// <param name="character">문자</param>

            /// <returns>포맷 문자열</returns>

            public virtual string Format(char character)

            {

                if(Formatter != null)

                {

                    return Formatter(character).ToString();

                }

 

                return character.ToString();

            }

 

            #endregion

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 마스크

        /// </summary>

        private string mask;

 

        /// <summary>

        /// 상징 리스트

        /// </summary>

        private ArrayList symbolList = new ArrayList();

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 마스크 - Mask

 

        /// <summary>

        /// 마스크

        /// </summary>

        public string Mask

        {

            get

            {

                return this.mask;

            }

            set

            {

                if(this.mask == value)

                {

                    return;

                }

 

                this.mask = value;

 

                UpdateText();

            }

        }

 

        #endregion

        #region 상징 - SymbolList

 

        /// <summary>

        /// 상징

        /// </summary>

        public ArrayList SymbolList

        {

            get

            {

                return this.symbolList;

            }

        }

 

        #endregion

        #region 숫자 텍스트 - NumericText

 

        /// <summary>

        /// 숫자 텍스트

        /// </summary>

        public string NumericText

        {

            get

            {

                string text = this.textBoxBase.Text;

 

                StringBuilder stringBuilder = new StringBuilder();

 

                foreach(char character in text)

                {

                    if(char.IsDigit(character))

                    {

                        stringBuilder.Append(character);

                    }

                }

 

                return stringBuilder.ToString();

            }

        }

 

        #endregion

        

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 -  MaskedBehavior(textBoxBase, mask)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        /// <param name="mask">마스크</param>

        public MaskedBehavior(TextBoxBase textBoxBase, string mask) : base(textBoxBase, true)

        {

            this.mask = mask;

 

            this.symbolList.Add(new Symbol('#', new Symbol.ValidatorMethod(char.IsDigit)));

        }

 

        #endregion

        #region 생성자 - MaskedBehavior(textBoxBase)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="textBoxBase">텍스트 박스 베이스</param>

        public MaskedBehavior(TextBoxBase textBoxBase) : this(textBoxBase, string.Empty)

        {

        }

 

        #endregion

        #region 생성자 - MaskedBehavior(behavior)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="behavior">마스크 동작</param>

        public MaskedBehavior(MaskedBehavior behavior) : base(behavior)

        {

            this.mask            = behavior.mask;

            this.symbolList = behavior.symbolList;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 텍스트 박스 베이스 키 DOWN 처리하기 - textBoxBase_KeyDown(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 키 DOWN 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected override void textBoxBase_KeyDown(object sender, KeyEventArgs e)

        {

            TraceLine("MaskedBehavior.textBoxBase_KeyDown " + e.KeyCode);

 

            if(e.KeyCode == Keys.Delete)

            {

                int startIndex;

                int endIndex;

 

                this.selection.GetSelection(out startIndex, out endIndex);

 

                string text   = this.textBoxBase.Text;

                int    length = text.Length;

 

                if(endIndex != length)

                {

                    if(!(endIndex == startIndex && endIndex == length - 1))

                    {

                        e.Handled = true;

                    }

                }

            }

        }

 

        #endregion

        #region 텍스트 박스 베이스 키 PRESS 처리하기 - textBoxBase_KeyPress(sender, e)

 

        /// <summary>

        /// 텍스트 박스 베이스 키 PRESS 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        protected override void textBoxBase_KeyPress(object sender, KeyPressEventArgs e)

        {

            TraceLine("MaskedBehavior.textBoxBase_KeyPress " + e.KeyChar);

 

            if(this.textBoxBase.ReadOnly)

            {

                return;

            }

 

            char character = e.KeyChar;

 

            e.Handled = true;

 

            int maskLength = this.mask.Length;

 

            if(maskLength == 0)

            {

                base.textBoxBase_KeyPress(sender, e);

 

                return;

            }

 

            int startIndex;

            int endIndex;

 

            this.selection.GetSelection(out startIndex, out endIndex);

 

            if(startIndex >= maskLength && character != (short)Keys.Back)

            {

                return;

            }

 

            string text   = this.textBoxBase.Text;

            int    length = text.Length;

 

            if(char.IsControl(character))

            {

                if(character == (short)Keys.Back && startIndex != length)

                {

                    SendKeys.Send("{LEFT}");

 

                    return;

                }

 

                base.textBoxBase_KeyPress(sender, e);

 

                return;

            }

 

            char maskCharacter = this.mask[startIndex];

 

            foreach(Symbol symbol in this.symbolList)

            {

                if(maskCharacter == (char)symbol)

                {

                    if(symbol.Validate(character))

                    {

                        endIndex = (endIndex == length ? endIndex : (startIndex + 1));

 

                        this.selection.ReplaceSelection(startIndex, endIndex, symbol.Format(character));

                    }

 

                    return;

                }

            }

 

            if(maskCharacter == character)

            {

                endIndex = (endIndex == length ? endIndex : (startIndex + 1));

 

                this.selection.ReplaceSelection(startIndex, endIndex, character.ToString());

 

                return;

            }

 

            StringBuilder stringBuilder = new StringBuilder();

 

            foreach(Symbol symbol in this.symbolList)

            {

                stringBuilder.Append((char)symbol);

            }

 

            char[] symbolCharacterArray = stringBuilder.ToString().ToCharArray();

 

            foreach(Symbol symbol in this.symbolList)

            {

                if(!symbol.Validate(character))

                {

                    continue;

                }

 

                string maskPortion = this.mask.Substring(startIndex);

 

                int maskPosition = maskPortion.IndexOfAny(symbolCharacterArray);

 

                if(maskPosition >= 0 && maskPortion[maskPosition] == (char)symbol)

                {

                    this.selection.ReplaceSelection

                    (

                        startIndex,

                        startIndex + maskPosition,

                        maskPortion.Substring(0, maskPosition)

                    );

 

                    textBoxBase_KeyPress(sender, e);

 

                    return;

                }

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 유효한 텍스트 구하기 - GetValidText()

 

        /// <summary>

        /// 유효한 텍스트 구하기

        /// </summary>

        /// <returns>유효한 텍스트</returns>

        protected override string GetValidText()

        {

            string text       = this.textBoxBase.Text;

            int    maskLength = this.mask.Length;

 

            if(maskLength == 0)

            {

                return text;

            }

 

            StringBuilder stringBuilder = new StringBuilder();

 

            int symbolCount = this.symbolList.Count;

 

            for(int position = 0, maskPosition = 0, length = text.Length; position < length; position++, maskPosition++)

            {

                char character     = text[position];

                char characterMask = (maskPosition < maskLength ? this.mask[maskPosition] : (char)0);

 

                if(characterMask == 0)

                {

                    break;

                }

 

                int symbolIndex = 0;

 

                for(; symbolIndex < symbolCount; symbolIndex++)

                {

                    Symbol symbol = (Symbol)this.symbolList[symbolIndex];

 

                    if(!symbol.Validate(character))

                    {

                        continue;

                    }

 

                    for(; maskPosition < maskLength; maskPosition++)

                    {

                        characterMask = this.mask[maskPosition];

 

                        if(characterMask == (char)symbol)

                        {

                            stringBuilder.Append(symbol.Format(character));

 

                            break;

                        }

                        else

                        {

                            int symbolCount2 = 0;

 

                            for(; symbolCount2 < symbolCount; symbolCount2++)

                            {

                                Symbol symbol2 = (Symbol)this.symbolList[symbolCount2];

 

                                if(characterMask == (char)symbol2)

                                {

                                    stringBuilder.Append(symbol.Format(character));

 

                                    break;

                                }

                            }

 

                            if(symbolCount2 < symbolCount)

                            {

                                break;

                            }

 

                            stringBuilder.Append(characterMask);

                        }

                    }

 

                    break;

                }

 

                if(symbolIndex == symbolCount)

                {

                    if(character == characterMask)

                    {

                        for(symbolIndex = 0; symbolIndex < symbolCount; symbolIndex++)

                        {

                            Symbol symbol = (Symbol)this.symbolList[symbolIndex];

 

                            if(characterMask == (char)symbol)

                            {

                                break;

                            }

                        }

 

                        if(symbolIndex == symbolCount)

                        {

                            stringBuilder.Append(character);

 

                            continue;

                        }

                    }

 

                    break;

                }

            }

 

            return stringBuilder.ToString();

        }

 

        #endregion

    }

}

 

 

Behaviors/DateBehavior.cs

 

 

using System;

using System.Diagnostics;

using System.Globalization;

using System.Text;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 날짜 동작

    /// </summary>

    public class DateBehavior : Behavior

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 플래그 - Flag

 

        /// <summary>

        /// 플래그

        /// </summary>

        [Flags]

        protected enum Flag

        {

            /// <summary>

            /// DAY_BEFORE_MONTH

            /// </summary>

            DAY_BEFORE_MONTH = 0x00010000

        };

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 범위 최소값

        /// </summary>

        private DateTime rangeMinimumValue = new DateTime(1900, 1, 1);

 

        /// <summary>

        /// 범위 최대값

        /// </summary>

        private DateTime rangeMaximumValue = new DateTime(9998, 12, 31);

 

        /// <summary>

        /// 분리자

        /// </summary>

        private char separator = '/';

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 월 - Month

 

        /// <summary>

        ///

        /// </summary>

        public int Month

        {

            get

            {

                string text          = this.textBoxBase.Text;

                int    startPosition = GetMonthStartPosition();

                int    slash         = text.IndexOf(this.separator);

 

                if(startPosition != 0 && slash > 0)

                {

                    startPosition = slash + 1;

                }

 

                if(text.Length >= startPosition + 2)

                {

                    return ToInt(text.Substring(startPosition, 2));

                }

 

                return 0;

            }

            set

            {

                using(SelectionSaver savedSelection = new SelectionSaver(this.textBoxBase))

                {

                    if(Month > 0)

                    {

                        this.selection.SetSelection(GetMonthStartPosition(), GetMonthStartPosition() + 3);

                    }

 

                    this.selection.Replace(GetTwoDigitString(value) + this.separator);

 

                    AdjustMaimumxDay();

 

                    if(!IsValidMonth(value))

                    {

                        throw new ArgumentOutOfRangeException();

                    }

                }

            }

        }

 

        #endregion

        #region 일 - Day

 

        /// <summary>

        ///

        /// </summary>

        public int Day

        {

            get

            {

                string text          = this.textBoxBase.Text;

                int    startPosition = GetDayStartPosition();

                int    slash         = text.IndexOf(this.separator);

 

                if(startPosition != 0 && slash > 0)

                {

                    startPosition = slash + 1;

                }

 

                if(text.Length >= startPosition + 2)

                {

                    return ToInt(text.Substring(startPosition, 2));

                }

 

                return 0;

            }

            set

            {

                if(!IsValidDay(value))

                {

                    throw new ArgumentOutOfRangeException();

                }

 

                using(SelectionSaver savedSelection = new SelectionSaver(this.textBoxBase))

                {

                    if(Day > 0)

                    {

                        this.selection.SetSelection(GetDayStartPosition(), GetDayStartPosition() + 3);

                    }

 

                    this.selection.Replace(GetTwoDigitString(value) + this.separator);

                }

            }

        }

 

        #endregion

        #region 연도 - Year

 

        /// <summary>

        /// 연도

        /// </summary>

        public int Year

        {

            get

            {

                string text   = this.textBoxBase.Text;

                int    length = text.Length;

                int    slash  = text.LastIndexOf(this.separator);

 

                if(slash > 0 && slash < length - 1)

                {

                    return ToInt(text.Substring(slash + 1, Math.Min(4, length - slash - 1)));

                }

 

                return 0;

            }

            set

            {

                if(!IsValidYear(value))

                {

                    throw new ArgumentOutOfRangeException();

                }

 

                using(SelectionSaver selectionSaver = new SelectionSaver(this.textBoxBase))

                {

                    if(Year > 0)

                    {

                        this.selection.SetSelection(GetYearStartPosition(), GetYearStartPosition() + 4);

                    }

 

                    this.selection.Replace(string.Format("{0,4:0000}", value));

 

                    AdjustMaximumMonthAndDay();

                }

            }

        }

 

        #endregion

        #region 값 - Value

 

        /// <summary>

        ///

        /// </summary>

        public object Value

        {

            get

            {

                try

                {

                    return new DateTime(Year, Month, Day);

                }

                catch

                {

                    return null;

                }

            }

            set

            {

                DateTime dateTime = (DateTime)value;

 

                this.textBoxBase.Text = GetFormattedDate(dateTime.Year, dateTime.Month, dateTime.Day);

            }

        }

 

        #endregion

        #region 에러 메시지 - ErrorMessage

 

        /// <summary>

        /// 에러 메시지

        /// </summary>

        public override string ErrorMessage

        {

            get

            {

                return "Please specify a date between " +

                       GetFormattedDate

                       (

                           this.rangeMinimumValue.Year,

                           this.rangeMinimumValue.Month,

                           this.rangeMinimumValue.Day

                       ) +

                       " and " +

                       GetFormattedDate

                       (

                           this.rangeMaximumValue.Year,

                           this.rangeMaximumValue.Month,

                           this.rangeMaximumValue.Day

                       ) +

                       ".";

            }

        }

 

        #endregion

        #region 범위 최소값 - RangeMinimumValue

 

        /// <summary>

        /// 범위 최소값

        /// </summary>

        public DateTime RangeMinimumValue

        {

            get

            {

                return this.rangeMinimumValue;

            }

            set

            {

                if(value < new DateTime(1900, 1, 1))

          &nb