C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

テキストボックスの文字数の制限を超えたらクリアしたい

[トピック内 18 記事 (1 - 18 表示)]  << 0 >>

■96281 / inTopicNo.1)  テキストボックスの文字数の制限を超えたらクリアしたい
  
□投稿者/ とんかつ (3回)-(2020/11/09(Mon) 16:37:58)

分類:[C#] 

2020/11/09(Mon) 16:44:54 編集(投稿者)
2020/11/09(Mon) 16:44:42 編集(投稿者)

テキストボックスの文字数の制限を超えたらクリアしたいです。
例えば"ABCDEFGHIJ"と入力して"K"を入力したら"ABCDEFGHIJ"はクリアされ、
Kから続きが入力されるようにするにはどうすればいいですか?
フォームアプリケーションで作っています。
private void textBox1_TextChanged(object sender, EventArgs e)
{
if(textBox1.TextLength == 10)
{
textBox1.Clear();
}

}

private void Form1_Load(object sender, EventArgs e)
{
textBox1.MaxLength = 10;
}
引用返信 編集キー/
■96283 / inTopicNo.2)  Re[1]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ 魔界の仮面弁士 (2904回)-(2020/11/09(Mon) 17:26:14)
No96281 (とんかつ さん) に返信
> テキストボックスの文字数の制限を超えたらクリアしたいです。
> 例えば"ABCDEFGHIJ"と入力して"K"を入力したら"ABCDEFGHIJ"はクリアされ、
> Kから続きが入力されるようにするにはどうすればいいですか?

・"ABCDEFGHIJ" の CDE が選択されている時に K と入力されると、
 通常は "ABKFGHIJ" と変わるはずですが、その場合も
 単に "K" だけにして良いのでしょうか。

・"ABCDEFGHIJ" の ABCDE と FGHIJ の間にカーソルがあるときに
 K と入力された場合はどうしますか? 通常は "ABCDEKFGHIJ" と変わるので、
 末尾となった "J" だけにするのでしょうか。それとも入力した "K" だけでしょうか。

・文字列の一部を反転している状態で、クリップボードから文字列がペーストされた場合や、
 手書き文字入力で挿入された文字列に対しては、どのように扱いますか?
引用返信 編集キー/
■96284 / inTopicNo.3)  Re[1]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ WebSurfer (2152回)-(2020/11/09(Mon) 17:26:53)
No96281 (とんかつ さん) に返信

期待した動きとどのように違うのでしょう?
引用返信 編集キー/
■96288 / inTopicNo.4)  Re[2]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ とんかつ (4回)-(2020/11/09(Mon) 20:56:05)
No96283 (魔界の仮面弁士 さん) に返信

> ・"ABCDEFGHIJ" の CDE が選択されている時に K と入力されると、
>  通常は "ABKFGHIJ" と変わるはずですが、その場合も
>  単に "K" だけにして良いのでしょうか。
>
> ・"ABCDEFGHIJ" の ABCDE と FGHIJ の間にカーソルがあるときに
>  K と入力された場合はどうしますか? 通常は "ABCDEKFGHIJ" と変わるので、
>  末尾となった "J" だけにするのでしょうか。それとも入力した "K" だけでしょうか。
>
> ・文字列の一部を反転している状態で、クリップボードから文字列がペーストされた場合や、
>  手書き文字入力で挿入された文字列に対しては、どのように扱いますか?


基本的な使い方はクリップボードから英数字10文字のコピペの繰り返しです。
次をコピペした時に以前の文字列がクリアされれば問題ありません。
引用返信 編集キー/
■96289 / inTopicNo.5)  Re[3]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ 魔界の仮面弁士 (2905回)-(2020/11/09(Mon) 21:21:58)
2020/11/09(Mon) 21:22:37 編集(投稿者)

No96288 (とんかつ さん) に返信
> 基本的な使い方はクリップボードから英数字10文字のコピペの繰り返しです。
> 次をコピペした時に以前の文字列がクリアされれば問題ありません。

あえて MaxLength は設定しないままにしておき、
TextChanged のタイミングで TextLength を調べ、
11 文字以上だった場合には、10 文字以下になるまで、
文字列先頭から 10 の倍数な文字数だけ
削ってみるのはどうでしょう。
引用返信 編集キー/
■96290 / inTopicNo.6)  Re[3]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ furu (91回)-(2020/11/09(Mon) 21:30:38)
No96288 (とんかつ さん) に返信
> 基本的な使い方はクリップボードから英数字10文字のコピペの繰り返しです。
一瞬でも最大20文字は入れられるようにしないといけないです。

MaxLengthの設定は不要ですね。

10文字超えてたら、先頭10文字消して
キャレットの位置を最後にすればいいと思います。

private void textBox1_TextChanged(object sender, EventArgs e)
{
    if (textBox1.Text.Length > 10)
    {
         textBox1.Text = textBox1.Text.Substring(10);
         textBox1.SelectionStart = textBox1.Text.Length;
    }
}

引用返信 編集キー/
■96293 / inTopicNo.7)  Re[4]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ 774RR (843回)-(2020/11/10(Tue) 06:20:43)
使う側からすればこの手の制約的 UI はもっての外で
長い文字列をコピーして
そのテキストボックスにペーストしてから不要なところを削る
つもりでいたら勝手に文字列が切り詰められていた
なんてことになって UX 最低。

仕様っつか仕様の前提となっている要望の見直しをお勧めしたい。

引用返信 編集キー/
■96294 / inTopicNo.8)  Re[5]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ とんかつ (5回)-(2020/11/10(Tue) 08:35:16)
2020/11/10(Tue) 08:52:55 編集(投稿者)

furuさんのやり方だと次をコピペしたら
先頭の文字が減ってしまいます。

魔界の仮面弁士さん、77RRさん
誤って11桁を入力しないように制限するのと
次のコピペをした時に以前の文字列が消えて新しい文字列が入れば
いいのですが自分はこの方法しか思いつきませんでした。
それを実現させる他のいい方法があるなら教えて頂きたいです。

引用返信 編集キー/
■96296 / inTopicNo.9)  Re[6]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ とっちゃん (703回)-(2020/11/10(Tue) 10:23:03)
No96294 (とんかつ さん) に返信

> 魔界の仮面弁士さん、77RRさん
> 誤って11桁を入力しないように制限するのと
> 次のコピペをした時に以前の文字列が消えて新しい文字列が入れば
> いいのですが自分はこの方法しか思いつきませんでした。
> それを実現させる他のいい方法があるなら教えて頂きたいです。
>
コピペ処理が特殊なら、テキストボックスにペーストで実現するより
別途貼り付けボタンを付けてそれを押させるとかのほうが誤操作を防止できると思いますがいかがでしょう?

手入力での処理も残しておけばいいと思うので、そちらはこれまでの実装のままで用意しておき
テキストボックスの近くに、貼り付けボタンを用意して中身を以下のような形で
全選択してペーストするとしてやれば、かなり手軽に処理できると思います。

textBox1.SelectAll();
textBox1.Paste();


引用返信 編集キー/
■96299 / inTopicNo.10)  Re[7]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ 774RR (845回)-(2020/11/10(Tue) 10:45:00)
最終的にテキストボックスに10文字が入っていなければならない(過不足があってはならない)なら

ShowDialog() だったら OK ボタンハンドラでバリデーションして文句言えばよい
メインフォームで実処理実行ボタンがあるなら、押された際にバリ以下略
常時実行したい何かだったら、タイマーでバリデーションしてステータス行にて文句言えばよい

ってことでオイラなら
・入力自体に制限を設けることはしない( TextBox.MaxLength=10 とかは使わない)
・いざ実行って直前にバリデーションする
・今***という理由で実行できないよってガイダンスがあると UX 的に正しい
くらいに留めておくっス。無駄に凝ったことをしても UX が増すとは思えないので。


引用返信 編集キー/
■96300 / inTopicNo.11)  Re[6]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ ビール呑み (3回)-(2020/11/10(Tue) 10:49:45)
No96294 (とんかつ さん) に返信

とんちんかんな回答だったらすみません。

テキストボックスにフォーカスが移った際に全選択状態にする、という方法論はどうでしょうか?

フォーカスが残ったままだとうまくいきませんが、ご参考まで。

引用返信 編集キー/
■96310 / inTopicNo.12)  Re[3]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ KOZ (150回)-(2020/11/10(Tue) 17:27:51)
No96288 (とんかつ さん) に返信
> 基本的な使い方はクリップボードから英数字10文字のコピペの繰り返しです。
> 次をコピペした時に以前の文字列がクリアされれば問題ありません。

こんな感じでどうでしょう?

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    class TextBoxEx : TextBox
    {
        const int WM_CHAR = 0x0102;
        const int WM_PASTE = 0x0302;

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_CHAR:
                    if (!Char.IsControl((char)m.WParam))
                    {
                        if (TextLength >= 10)
                        {
                            this.Clear();
                        }
                    }
                    base.WndProc(ref m);
                    break;

                case WM_PASTE:
                    if (Clipboard.ContainsText())
                    {
                        var ctx = Clipboard.GetText();
                        foreach (var c  in ctx)
                        {
                            SendMessage(this.Handle, WM_CHAR, (IntPtr)c, (IntPtr)1);
                        }
                    }
                    break;

                default:
                    base.WndProc(ref m);
                    break;
            }
        }
    }
}

引用返信 編集キー/
■96315 / inTopicNo.13)  Re[6]: テキストボックスの文字数の制限を超えたらクリアしたい
□投稿者/ furu (92回)-(2020/11/10(Tue) 20:14:37)
No96294 (とんかつ さん) に返信
> furuさんのやり方だと次をコピペしたら
> 先頭の文字が減ってしまいます。
試してみましたが減らないですね。
ペーストの仕方とか違うのかな。
引用返信 編集キー/
■96317 / inTopicNo.14)  Re[4]: テキストボックスの文字数の制限を超えたらクリア
□投稿者/ 夜叉姫 (2回)-(2020/11/11(Wed) 11:43:06)
2020/11/11(Wed) 11:46:24 編集(投稿者)
これじゃだめですか?

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
	if (textBox1.Text.Length >= 10)
	{
		textBox1.Text = "";
	}
}

あと、BSキーなどで文字が減るなど特殊な場合を
考慮すればいいと思います。

引用返信 編集キー/
■96318 / inTopicNo.15)  Re[5]: テキストボックスの文字数の制限を超えたらクリア
□投稿者/ furu (93回)-(2020/11/11(Wed) 11:59:18)
No96317 (夜叉姫 さん) に返信
> これじゃだめですか?
最初、「入力したら」と書かれていましたが
実際はコピペするそうなんで
KeyPressイベント発生しないです。
引用返信 編集キー/
■96325 / inTopicNo.16)  Re[6]: テキストボックスの文字数の制限を超えたらクリア
□投稿者/ 夜叉姫 (3回)-(2020/11/11(Wed) 13:50:35)
2020/11/11(Wed) 13:55:19 編集(投稿者)

No96318 (furu さん) に返信

テキストがない状態で
abcdefghij を貼り付け(ctrl+V)して abcdefghij にして
klmnopqrst を貼り付け(ctrl+V)すると klmnopqrst になります。

>例えば"ABCDEFGHIJ"と入力して"K"を入力したら"ABCDEFGHIJ"はクリアされ、
>Kから続きが入力されるようにするにはどうすればいいですか?

>基本的な使い方はクリップボードから英数字10文字のコピペの繰り返しです。
>次をコピペした時に以前の文字列がクリアされれば問題ありません。

どちらも思う通りの動きになります。



追記>
すみません。
個人的に、貼り付けは Ctrl+V でするので気が付きませんでしたが
右クリックして貼り付けすると KeyPress は発生しませんね。



引用返信 編集キー/
■96326 / inTopicNo.17)  Re[7]: テキストボックスの文字数の制限を超えたらクリア
□投稿者/ 魔界の仮面弁士 (2908回)-(2020/11/11(Wed) 14:29:48)
2020/11/11(Wed) 14:32:33 編集(投稿者)

No96294 (とんかつ さん) に返信
> furuさんのやり方だと次をコピペしたら
> 先頭の文字が減ってしまいます。

何か他の処理が併用されていないでしょうか?
(たとえば、IME や SEP の on/off 制御とか、フォーカスの強制移動処理とか)


また、複数の実装方法を同時に試していたりはしないでしょうか。

ここまでに幾つかの案が提示されていますが、
Text が変更されてから補正する方法(TextChanged 等)もあれば、
Text が変更される前にクリア処理する方法(KeyPress 等)もあるので、
組み合わせ方を間違えると、誤動作するかも知れません。



No96325 (夜叉姫 さん) に返信
> テキストがない状態で
> abcdefghij を貼り付け(ctrl+V)して abcdefghij にして
> klmnopqrst を貼り付け(ctrl+V)すると klmnopqrst になります。

クリップボードの中身が 11 文字以上あった時の処置も
考えておいた方が良いかもしれませんね。

クリップボードにコピーする際に、うっかり前後の
改行やタブを含めてしまうことがあるかも知れませんので。


> 個人的に、貼り付けは Ctrl+V でするので気が付きませんでしたが
> 右クリックして貼り付けすると KeyPress は発生しませんね。

キーボードからの操作であったとしても、
[Shift]+[Insert] での貼り付け操作(※)や
[Shift]+[F10] あるいは [Application] キーのコンテキストメニューでも
KeyPress イベントが発生しない事になります。

※Shift + Insert は、16 bit 版 Windows の頃からある貼り付けショートカットです。
 Ctrl+C は、コマンド プロンプトの動作を停止させてしまうといった弊害があるため、
 Ctrl+C / Ctrl+X / Ctrl+V の代わりに、あえて昔ながらの
 Ctrl+Insert / Shift+Delete / Shift+Insert を好む人たちも居ます。


しかし No96310 で KOZ さんが書かれている WM_PASTE を捕らえる方法であれば、
マウス等からの貼り付け動作でも、正しく捉えられると思います。

マウスの右クリックの他、Windows Touch や Pen からのジェスチャー操作や
ロングタップによるコンテキストメニューに対しても、KeyPress では
捉えきれませんが、WM_PASTE メッセージならば拾えそうです。



個人的には No96296 のとっちゃんさんの方法に一票。

11 文字目を入れようとすると文字が突然消えてしまうという UI は、初めて見る人を混乱させますが、
貼り付けボタンを押すとクリップボードの中身で置き換えられるという動作なら、初見でも分かりやすそう。
引用返信 編集キー/
■96327 / inTopicNo.18)  Re[8]: テキストボックスの文字数の制限を超えたらクリア
□投稿者/ とんかつ (6回)-(2020/11/11(Wed) 15:00:51)
みなさまアドアイスありがとうございます。
いろいろアドバイス通り試してみましたがとっちゃんさんの方法でいってみたいと思います。
みなさんありがとうございました。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ