QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

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

C#初心者です。

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

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

どなたかご教授ください。

質問者:ぽんた

回答

判断を TextChanged イベントでするようにすればどうでしょう。
この場合は処理済みとマークする(e.Handle を true にする)のではなく、Text プロパティを直接置き換えることになりますが。

投稿者:Hongliang

編集 履歴 (0)

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

テキストボックスに全角文字を入力したタイミングでバイト数チェック

を行いバイト数を超えていたら入力されないようにしたいのですが方法がわかりません。

現在、入力文字を解除するため、KeyPressEventArgs.Handledプロパティを

trueを設定してるのですが半角文字入力したときしか入力文字が解除されません。

(全角文字入力しEnterキーを押したタイミングでは入力されてしまいます)

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

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

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

[ メッセージ編集済み 編集者: じゃんぬねっと 編集日時 2006-09-19 14:39 ]

投稿者:じゃんぬねっと

編集 履歴 (0)

TextChangedでバイト数制限を対応してみたんですが全角文字で一度に複数文字列を
入力した場合以下のような不具合が発生してしまいます。

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

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

なにか解決策はありますでしょうか?

投稿者:ぽんた

編集 履歴 (0)

埋まる前に投下しときます。



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 の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

スレ主ではありませんが、上記じゃんぬねっとさんのコードについて
参考にさせて頂きましたので、フィードバックします。

バッチリ動きました。
ありがとうございます。

投稿者:未記入

編集 履歴 (0)

一郎さんのサンプルソースの内容で対応できました。

みなさん本当にありがとうございました。

投稿者:ぽんた

編集 履歴 (0)

未記入さんの書き込み (2006-03-20 11:25) より:

スレ主ではありませんが、上記じゃんぬねっとさんのコードについて

参考にさせて頂きましたので、フィードバックします。

バッチリ動きました。ありがとうございます。

検証とフィードバック、ありがとうございます。(*_ _)
テストをせずに投下したので心配でしたが、安心しました。

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

投稿者:じゃんぬねっと

編集 履歴 (0)

どうでもいいことですが、あれだと TextBox の数分呼び出したりイベント ハンドラに登録しなければいけないような。
それと、ながーい文字列をペーストされたりするとチラついたりしないのでしょうか...

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

投稿者:じゃんぬねっと

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。