- PR -

c# テキストボックスに全角文字バイト数制限を制御したい

投稿者投稿内容
ぽんた
会議室デビュー日: 2005/12/27
投稿数: 17
投稿日時: 2006-02-23 20:11
C#初心者です。

テキストボックスに全角文字を入力したタイミングでバイト数チェック
を行いバイト数を超えていたら入力されないようにしたいのですが方法が
わかりません。

現在、入力文字を解除するため、KeyPressEventArgs.Handledプロパティを
trueを設定してるのですが半角文字入力したときしか入力文字が解除されません。
(全角文字入力しEnterキーを押したタイミングでは入力されてしまいます)

どなたかご教授ください。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2006-02-23 20:29

判断を TextChanged イベントでするようにすればどうでしょう。
この場合は処理済みとマークする(e.Handle を true にする)のではなく、Text プロパティを直接置き換えることになりますが。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-23 20:38
引用:

あやちんさんの書き込み (2006-02-23 20:11) より:

テキストボックスに全角文字を入力したタイミングでバイト数チェック
を行いバイト数を超えていたら入力されないようにしたいのですが方法がわかりません。

現在、入力文字を解除するため、KeyPressEventArgs.Handledプロパティを
trueを設定してるのですが半角文字入力したときしか入力文字が解除されません。
(全角文字入力しEnterキーを押したタイミングでは入力されてしまいます)


KeyPress イベントで捕えられたとしても、危険でしょう。
ペーストなどには対応できません。

TextChanged イベントによる実装が最も現実的でしょう。
ただし、チラツキをなくす工夫が必要になります。

TextBox の派生クラスを作り、WndProc メソッドをオーバーライドして、
WM_CHAR を捕捉し、このタイミングでバイト数の制限を行うのもひとつの手でしょう。

# 何故か ComboBox になっていたので修正... orz

[ メッセージ編集済み 編集者: じゃんぬねっと 編集日時 2006-09-19 14:39 ]
ぽんた
会議室デビュー日: 2005/12/27
投稿数: 17
投稿日時: 2006-02-24 14:10
TextChangedでバイト数制限を対応してみたんですが全角文字で一度に複数文字列を
入力した場合以下のような不具合が発生してしまいます。

たとえば入力制限4バイトで"あいうえ"と一度の確定で入力すると
結果は"あい"になるはずですが"えあ"となってしまいます。

デバッグしてみた結果
 ・一度に複数文字入力確定した場合でもTextChangedは1文字ずつ実行される
 ・入力制限オーバーの場合Textプロパティを再設定
(上記"あいう"のタイミングで"あい"を設定)
 ・再設定のタイミングでTextChangedが実行されこのときTextプロパティの値が
  "えあい"となってしまい、バイト数チェックに再度引っかかって
  結果が"えあ"となってしまっている

なにか解決策はありますでしょうか?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-24 14:18
埋まる前に投下しときます。

コード:
using System.ComponentModel;

namespace Jeanne.Windows.Forms {

    public class ExTextBox : System.Windows.Forms.TextBox {

      #region コンストラクタ 

        private System.ComponentModel.Container components = null;

        public ExTextBox() {
            this.components = new System.ComponentModel.Container();
            this.MaxByteLength = int.MaxValue;
        }

      #endregion

      #region MaxByteLength プロパティ 

        private int _MaxByteLength;

        [Category("動作")]
        [DefaultValue(int.MaxValue)]
        [Description("エディット コントロールに入力できる最大文字バイト数を指定します。")]
        [RefreshProperties(RefreshProperties.Repaint)]
        public int MaxByteLength {
            get {
                return this._MaxByteLength;
            } set {
                this._MaxByteLength = value;

                int iMaxLength = (int)System.Math.Ceiling(value / 2);

                if (iMaxLength > this.MaxLength) {
                    this.MaxLength = iMaxLength;
                }
            }
        }

      #endregion

      #region MaxLength プロパティ (override) 

        [RefreshProperties(RefreshProperties.Repaint)]
        public override int MaxLength {
            get {
                return base.MaxLength;
            } set {
                base.MaxLength = value;

                int iMaxByteLength = value * 2;

                if (iMaxByteLength > this.MaxByteLength) {
                    this.MaxByteLength = iMaxByteLength;
                }
            }
        }

      #endregion

      #region Dispose メソッド (override) 

        protected override void Dispose(bool disposing) {
            if (disposing) {
                if (this.components != null) {
                    components.Dispose();
                }
            }

            base.Dispose(disposing);
        }

      #endregion

      #region IsInputChar メソッド (override) 

        protected override bool IsInputChar(char charCode) {
            base.IsInputChar(charCode);

            return false;
        }

      #endregion

      #region ProcessDialogChar メソッド 

        protected override bool ProcessDialogChar(char charCode) {
            base.ProcessDialogChar(charCode);

            System.Text.Encoding sjisEncoding = System.Text.Encoding.GetEncoding("Shift_JIS");
            int inputByteCount = sjisEncoding.GetByteCount(charCode.ToString());
            int textByteCount  = sjisEncoding.GetByteCount(this.Text);

            if (char.IsControl(charCode)) {
                return false;
            }

            if ((textByteCount + inputByteCount) > this.MaxByteLength) {
                return true;
            }

            return false;
        }

      #endregion

    }

}


テストはしていないので不具合があるかもしれません...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2006-02-24 14:23
昔こんなのありました。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=10370&forum=7
ぽんた
会議室デビュー日: 2005/12/27
投稿数: 17
投稿日時: 2006-02-24 18:49
一郎さんのサンプルソースの内容で対応できました。

みなさん本当にありがとうございました。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-24 19:31
どうでもいいことですが、あれだと TextBox の数分呼び出したりイベント ハンドラに登録しなければいけないような。
それと、ながーい文字列をペーストされたりするとチラついたりしないのでしょうか...

# 結果だけ見ればどうでもいいことなんでしょうけど。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)