using System;
          using System.ComponentModel;
          using System.Linq;
          using System.Windows.Forms;

          namespace RCRS.WinLibrary.Presentation.UI
          {
              //--------------------------------------------------------------------------
              /// <summary>
              
          /// 數値テキストボックス
              
          /// </summary>
              //--------------------------------------------------------------------------
              [DefaultBindingProperty("Value")]
              public partial class CtrlDecimalBox : TextBox
              {
                  private decimal? maxValue     = 99999.99M;
                  private decimal? minValue     = 0.0M;
                  private decimal? value        = null;
                  private int? decimalDigits    = null;
                  private char decimalSeparator = '.';
                  private char groupSeparator   = ',';
                  private char negativeSign     = '-';
                  private bool useGroup         = true;
                  private bool useLimit         = false;

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// バリューが限界を超えるデリゲートです。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  public delegate void DecimalBoxBeyondLimitHandler(object sender, BeyondLimitEventArgs bevent);

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// バリューが限界を超えたら、発生します。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  public event DecimalBoxBeyondLimitHandler BeyondLimit;

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// Valueがチェンジしたら、発生します。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  public event EventHandler ValueChanged;

                  #region 屬性設定

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 整數部分をグループ區切る記號で分けるかのプロパティ
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [DefaultValue(true)]
                  [Description("整數部分をグループ區切る記號で分けるかどうか")]
                  [Category("DecimalSetting")]
                  public bool UseGroup
                  {
                      get { return useGroup; }
                      set { useGroup = value; }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 小數點以下桁數を設定します。
                  
          /// Nullにしたら桁數の制限がなくなる
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [DefaultValue(null)]
                  [Description("小數點以下桁數を設定します。Nullにしたら桁數の制限がなくなる")]
                  [Category("DecimalSetting")]
                  public int? DecimalDigits
                  {
                      get { return decimalDigits; }
                      set
                      {
                          if (value == null)
                              decimalDigits = value;
                          else if (value < 0)
                              decimalDigits = null;
                          else
                              decimalDigits = value;
                      }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 限界値を使用するかのプロパティ
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [DefaultValue(false)]
                  [Description("限界値を使用するかどうか")]
                  [Category("DecimalSetting")]
                  public bool UseLimit
                  {
                      get { return useLimit; }
                      set { useLimit = value; }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 最大値のプロパティ
                  
          /// Nullにしたら最大値を判斷しません
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [DefaultValue(typeof(decimal), "99999.99")]
                  [Description("最大値のプロパティ,Nullにしたら最大値を判斷しません")]
                  [Category("DecimalSetting")]
                  public decimal? MaxValue
                  {
                      get { return maxValue; }
                      set
                      {
                          if (value == null)
                              maxValue = value;
                          else if (value <= minValue)
                              maxValue = minValue + 1;
                          else
                              maxValue = value;
                      }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 最小値のプロパティ
                  
          /// Nullにしたら最小値を判斷しません
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [DefaultValue(typeof(decimal), "0.0")]
                  [Description("最小値のプロパティ,Nullにしたら最小値を判斷しません")]
                  [Category("DecimalSetting")]
                  public decimal? MinValue
                  {
                      get { return minValue; }
                      set
                      {
                          if (value == null)
                              minValue = value;
                          else if (value >= maxValue)
                              minValue = maxValue - 1;
                          else
                              minValue = value;
                      }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 整數と小數を區切る記號(.)
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [DefaultValue('.')]
                  [Description("整數と小數を區切る記號(.)")]
                  [Category("DecimalSetting")]
                  public char DecimalSeparator
                  {
                      get { return decimalSeparator; }
                      set
                      {
                          if (value != decimalSeparator &&
                              value != groupSeparator &&
                              value != negativeSign)
                              decimalSeparator = value;
                      }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 整數グループを區切る記號(,)
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [DefaultValue(',')]
                  [Description("整數グループを區切る記號(,)")]
                  [Category("DecimalSetting")]
                  public char GroupSeparator
                  {
                      get { return groupSeparator; }
                      set
                      {
                          if (value != decimalSeparator &&
                              value != groupSeparator &&
                              value != negativeSign)
                              groupSeparator = value;
                      }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 數値が負であることを示す記號(-)
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [DefaultValue('-')]
                  [Description("數値が負であることを示す記號(-)")]
                  [Category("DecimalSetting")]
                  public char NegativeSign
                  {
                      get { return negativeSign; }
                      set
                      {
                          if (value != decimalSeparator &&
                              value != groupSeparator &&
                              value != negativeSign)
                              negativeSign = value;
                      }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 數字値のプロパティ
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [Bindable(true)]
                  [DefaultValue("")]
                  [Description("數字値のプロパティ")]
                  [Category("DecimalSetting")]
                  public string Value
                  {
                      get { return value.ToString(); }
                      set { setValue(value, true); }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 親クラスのプロパティです、DataBindできないように処理されました。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  [Bindable(false)]
                  [DefaultValue("")]
                  public override string Text
                  {
                      get { return base.Text; }
                      set { base.Text = value; }
                  }

                  #endregion

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// CtrlDecimalBoxのインスタンスを作成します。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  public CtrlDecimalBox()
                  {
                      InitializeComponent();
                      ImeMode = ImeMode.Disable;
                      DataBindings.CollectionChanged += new CollectionChangeEventHandler(DataBindings_CollectionChanged);
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// valueが変わったときの処理メソッド
                  
          /// </summary>
                  //--------------------------------------------------------------
                  protected virtual void OnValueChanged(object sender, EventArgs eventArgs)
                  {
                      if (ValueChanged != null)
                          ValueChanged(this, EventArgs.Empty);
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// valueのあたいが限界を超えたら、発生します。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  protected virtual void OnBeyondLimit(object sender, BeyondLimitEventArgs bevent)
                  {
                      if (BeyondLimit != null)
                          BeyondLimit(this, bevent);
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// コントロールにエンターするとき、Control.Enterイベントを発生させて、カンマを抜きます。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  protected override void OnEnter(EventArgs e)
                  {
                      base.OnEnter(e);
                   
                      string tmpStr = stringtoNumStr(Text);
                      Text = tmpStr;
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// Control.KeyDownイベントを発生させます。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  protected override void OnKeyDown(KeyEventArgs e)
                  {
                      base.OnKeyDown(e);
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// Control.KeyPressイベントを発生させて、許容されるキーだけを処理します。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  protected override void OnKeyPress(KeyPressEventArgs e)
                  {
                      base.OnKeyPress(e);
                      if (Char.IsDigit(e.KeyChar) &&      //數字が入力されたとき
                          ((Text.Contains(negativeSign) &&
                          SelectionStart != 0) ||    //「-」があり先頭以外にカーソルがあるとき
                          ((Text.Contains(negativeSign) &&
                          SelectionStart == 0) &&
                          0 < SelectionLength) ||     //「-」があり先頭から文字列が選択狀態のとき
                          (!Text.Contains(negativeSign))))  // 「-」がないとき
                      {
                      }
                      else if (e.KeyChar == '\b')
                      {
                      }
                      else if (e.KeyChar == decimalSeparator    &&
                          !Text.Contains(decimalSeparator) &&
                          SelectionStart != 0 &&
                          decimalDigits != 0)
                      {
                      }
                      else if (e.KeyChar == negativeSign    &&
                          !Text.Contains(negativeSign) &&
                          SelectionStart == 0)
                      {
                      }
                      else if (e.KeyChar == negativeSign    &&   //全選択した狀態で、「-」マイナスが入力できるように追加します。
                          SelectionStart == 0               &&
                          SelectionLength > 0)
                      {
                      }
                      else
                      {
                          e.Handled = true;
                      }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// テキストを変更して、Control.KeyUpイベントを発生させます。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  protected override void OnKeyUp(KeyEventArgs e)
                  {
                      if (!e.Handled)
                      {
                          string tmpStr = stringtoNumStr(Text);
                          if (tmpStr != "-")  //1文字目「-」のとき入力許可
                              setValue(tmpStr, false);
                      }
                      base.OnKeyUp(e);
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// テキストボックスがフォーカスを失ったとき、発生します。
                  
          /// </summary>
                  
          /// <param name="e"></param>
                  //--------------------------------------------------------------
                  protected override void OnLostFocus(EventArgs e)
                  {
                      handleText();
                      base.OnLostFocus(e);
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// データバインディング
                  
          /// </summary>
                  
          /// <param name="sender"></param>
                  
          /// <param name="e"></param>
                  //--------------------------------------------------------------
                  private void DataBindings_CollectionChanged(object sender, CollectionChangeEventArgs e)
                  {
                      if (e.Element != null)
                      {
                          if (e.Action == CollectionChangeAction.Add)
                              ((Binding)e.Element).Parse += new ConvertEventHandler(CtrlDecimalBox_Parse);
                          else if (e.Action == CollectionChangeAction.Remove)
                              ((Binding)e.Element).Parse -= CtrlDecimalBox_Parse;
                      }
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// バインディングのParseイベントハンドラー
                  
          /// </summary>
                  
          /// <param name="sender"></param>
                  
          /// <param name="e"></param>
                  //--------------------------------------------------------------
                  private void CtrlDecimalBox_Parse(object sender, ConvertEventArgs e)
                  {
                      if (e.Value.ToString() == "")
                          e.Value = DBNull.Value;
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 文字列から數字へ変換して、valueに値を付ける。
                  
          /// </summary>
                  
          /// <param name="strValue">Valueに付けたい値</param>
                  
          /// <param name="changText">テキストを更新しますか</param>
                  //--------------------------------------------------------------
                  private void setValue(string strValue, bool changText)
                  {
                      decimal? tmp = null;
                      bool isNullableNum = true;

                      //strValueをNullableDecimalに変換します。
                      if (strValue == "" || strValue == null)
                          tmp = null;
                      else
                      {
                          decimal tmp1;
                          if (pretreatment(strValue, out tmp1))
                              tmp = tmp1;
                          else
                              isNullableNum = false;
                      }
                      int limit = 0;
                      //変換成功したかどうかを判斷して、処理します。
                      if (isNullableNum)
                      {
                          if (value != tmp)
                          {
                              value = tmp;
                              limit = handleBeyondLimit();
                              OnValueChanged(this, EventArgs.Empty);
                          }
                          if (!Focused)
                              Text = numbertoString(value);
                      }
                      else
                      {
                          if (changText)
                              Text = numbertoString(value);
                          else
                              Text = eraseComma(numbertoString(value));
                      }
                      //限界を超えたら、BeyondLimitイベントを発生させます。
                      if (limit == -1)
                          OnBeyondLimit(thisnew BeyondLimitEventArgs(tmp, DecimalBoxBeyondKind.BeyondMinValue));
                      else if (limit == 1)
                          OnBeyondLimit(thisnew BeyondLimitEventArgs(tmp, DecimalBoxBeyondKind.BeyondMaxValue));
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 科學的表記法された數字を処理して、デシマルに変換。
                  
          /// </summary>
                  
          /// <param name="strValue">入力された數字(文字列型)</param>
                  
          /// <param name="outDec">出力される數字</param>
                  
          /// <returns>処理成功したかどうか</returns>
                  //--------------------------------------------------------------
                  private bool pretreatment(string strValue, out decimal outDec)
                  {
                      string tmpStr = strValue.ToLower();
                      decimal number = 0m;
                      decimal index = 0m;
                      bool result = false;
                      try
                      {
                          if (tmpStr.Contains("e"))
                          {
                              number = Convert.ToDecimal(tmpStr.Split('e')[0]);
                              index = Convert.ToDecimal(tmpStr.Split('e')[1]);
                              for (int i = 0; Math.Abs(i) < Math.Abs(index); )
                              {
                                  if (index > 0)
                                  {
                                      number = number * 10m;
                                      i++;
                                  }
                                  else
                                  {
                                      number = number / 10m;
                                      i--;
                                  }
                              }
                              strValue = number.ToString();
                          }
                          if (Decimal.TryParse(strValue, out number))
                              result = true;
                          else
                              result = false;
                      }
                      catch
                      {
                          result = false;
                      }
                      outDec = number;
                      return result;
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 限界を越えたかどうかを判斷し、バリューを処理します。
                  
          /// 超えなかったら0で、最大値より大きいなら1で、最小値より小さいなら-1です。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  private int handleBeyondLimit()
                  {
                      int result = 0;
                      if (useLimit && value != null)
                      {
                          if (minValue != null && value < minValue)
                          {
                              value = minValue;
                              result = -1;
                          }
                          else if (maxValue != null && value > maxValue)
                          {
                              value = maxValue;
                              result = 1;
                          }
                      }
                      return result;
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// 変わったテキストを処理します。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  private void handleText()
                  {
                      string tmpStr;
                      tmpStr = stringtoNumStr(Text);
                      setValue(tmpStr, true);
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// テキストを標準數字の文字列に変換します(カンマなし)
                  
          /// </summary>
                  
          /// <param name="str">変換したい文字列</param>
                  //--------------------------------------------------------------
                  private string stringtoNumStr(string str)
                  {
                      string decimalPart = "";
                      string sign = "";
                      if (str.Contains(negativeSign))
                      {
                          sign = "-";
                          str = str.Replace(negativeSign.ToString(), "");
                      }
                      str = str.Replace(groupSeparator.ToString(), "");
                      str = str.Replace(decimalSeparator.ToString(), ".");

                      if (str.Contains('.'))
                      {
                          decimalPart = str.Split('.')[1];
                          if (decimalPart.Length != 0)
                          {
                              if (decimalDigits != null)
                              {
                                  if (decimalDigits < decimalPart.Length)
                                  {
                                      str = str.Remove(str.IndexOf('.') + (int)decimalDigits + 1);
                                  }
                              }
                          }
                          else
                              str = str.Replace(".", "");
                      }
                      str = sign + str;
                      return str;
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// コントロールのプロパティによって數字を表示します。
                  
          /// </summary>
                  
          /// <param name="num">変換したい數字</param>
                  //--------------------------------------------------------------
                  private string numbertoString(decimal? num)
                  {
                      if (num != null)
                      {
                          string integerPart = "";
                          string decimalPart = "";
                          string result      = "";
                          string point       = "";
                          string sign        = "";
                          //句読點を処理して、整數と小數を分けます。
                          result = num.ToString();
                          if (result.Contains('-'))
                          {
                              sign = negativeSign.ToString();
                              result = result.Replace("-", "");
                          }
                          if (result.Contains('.'))
                          {
                              integerPart = result.Split('.')[0];
                              decimalPart = result.Split('.')[1];
                          }
                          else
                              integerPart = result;
                          if ((decimalDigits == null && decimalPart != "") ||
                              (decimalDigits != null && decimalDigits != 0))
                              point = decimalSeparator.ToString();

                          //整數部分を処理します。
                          if (useGroup)
                          {
                              string tmp = "";
                              if (integerPart.Length % 3 != 0)
                              {
                                  tmp += integerPart.Substring(0, integerPart.Length % 3);
                                  tmp += groupSeparator.ToString();
                                  integerPart = integerPart.Remove(0, integerPart.Length % 3);
                              }
                              for (int i = 0; i * 3 < integerPart.Length; i++)
                              {
                                  tmp += integerPart.Substring(i * 3, 3);
                                  tmp += groupSeparator.ToString();
                              }
                              tmp = tmp.Remove(tmp.Length - 1, 1);
                              integerPart = tmp;
                          }
                          //小數部分を処理します。
                          if (decimalDigits != null)
                          {
                              if (decimalPart.Length < (int)decimalDigits)
                              {
                                  int tmpLength = decimalPart.Length;

                                  for (int i = 0; i < decimalDigits - tmpLength; i++)
                                      decimalPart += "0";
                              }
                              else
                                  decimalPart = decimalPart.Substring(0, (int)decimalDigits);
                          }
                          //総合処理
                          result = sign + integerPart + point + decimalPart;
                          return result;
                      }
                      else
                          return "";
                  }

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// コントロールのプロパティによってフォーマットした文字列のカンマを抜きます。
                  
          /// </summary>
                  
          /// <param name="str">カンマを抜きたい文字列</param>
                  //--------------------------------------------------------------
                  private string eraseComma(string str)
                  {
                      str = str.Replace(groupSeparator.ToString(), "");
                      string sign = "";

                      if (str.Contains('-'))
                      {
                          sign = negativeSign.ToString();
                          str = str.Replace("-", "");
                      }
                      if (str.Contains('.'))
                      {
                          str = str.Replace('.', decimalSeparator);
                      }
                      str = sign + str;
                      return str;
                  }
              }

              //--------------------------------------------------------------
              /// <summary>
              
          /// BeyondLimitEventArgs、BeyondLimitイベントの引數クラスです
              
          /// </summary>
              //--------------------------------------------------------------
              public class BeyondLimitEventArgs : EventArgs
              {
                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// BeyondLimitの種類を示す。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  public DecimalBoxBeyondKind BeyondKind;
                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// BeyondLimitイベントを起こすバリューです。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  public decimal? Value;
                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// BeyondLimitEventArgsのインスタンスを作成します。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  public BeyondLimitEventArgs(decimal? value, DecimalBoxBeyondKind beyondKind)
                  {
                      Value = value;
                      BeyondKind = beyondKind;
                  }
              }

              //--------------------------------------------------------------
              /// <summary>
              
          /// BeyondLimitの種類を示す列挙型です。
              
          /// </summary>
              //--------------------------------------------------------------
              public enum DecimalBoxBeyondKind
              {
                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// MaxValueを超えた。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  BeyondMaxValue,

                  //--------------------------------------------------------------
                  /// <summary>
                  
          /// MinValueを超えた。
                  
          /// </summary>
                  //--------------------------------------------------------------
                  BeyondMinValue,
              }
          }

          posted on 2016-12-23 14:20 Ying-er 閱讀(193) 評論(0)  編輯  收藏 所屬分類: .Net

          填坑女俠  

          <2016年12月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          友情鏈接

          各人常用鏈接

          搜索

          •  

          積分與排名

          • 積分 - 194260
          • 排名 - 296

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 丹寨县| 诏安县| 莱阳市| 五指山市| 读书| 成都市| 乐清市| 榕江县| 怀柔区| 株洲市| 景泰县| 新绛县| 安平县| 南通市| 都昌县| 临海市| 光山县| 广昌县| 肥西县| 江城| 阿克苏市| 延边| 大英县| 林口县| 彭山县| 泗水县| 怀安县| 台东县| 镇赉县| 许昌县| 中西区| 乐业县| 且末县| 永和县| 诸城市| 邹平县| 郸城县| 于都县| 桓台县| 友谊县| 鄂尔多斯市|