30


10

Winforms Textbox - Ctrl-Backspaceを使って単語全体を削除する

私は、他のコントロールの中に、一行の入力を可能にするTextBoxを含むWinformsダイアログを持っています。 ユーザーがCtrl-Backspaceを押して単語全体を削除できるようにしたい。 これはデフォルトのTextBoxのデフォルトの動作ではありません。単語を削除するのではなく、_rectangle_文字を受け取ります。

`+ ShortcutsEnabled `プロパティが ` True +`に設定されていることを確認しました。

必要な動作を得るために、TextBoxではなくRichTextBoxを使用できることがわかりました。 これに関する問題は、RichTextBoxの外観(特にボーダー)がTextBoxの外観とは異なること、そしてテキストをマークアップする機能を必要としない、または必要としないことです。

それで、私の質問は、この状況にどう対処するかということです。 TextBoxに欠けているプロパティがありますか? それとも、RichTextBoxを使用し、外観が一貫するように更新し、テキストのマークアップを無効にするのが最善ですか?

これ以上の方法がない場合は、KeyDownイベントとKeyPressイベントを明示的に処理するコードを作成しても嬉しいですが、最初に確認する価値があると思いました。

11 Answer


23


  • / *更新:下記のDamirの回答もご覧ください。おそらくより良い解決策です:) * / *

Ctrlキーを押しながら左とBackspaceをTextBoxに送信して、Ctrl Backspaceをシミュレートします。 効果はほぼ同じで、コントロールのテキストを手動で処理する必要はありません。 あなたはこのコードを使ってそれを達成することができます:

TextBoxEx:TextBox {protected override bool ProcessCmdKey(Ref Message msg、Keys keyData){if(keyData ==(Keys.Control | Keys.Back)){SendKeys.SendWait( "^ {LEFT} {BACKSPACE}"); trueを返します。 base.ProcessCmdKey(ref msg、keyData);を返します。 }}

app.configファイルを変更して、SendKeyクラスに新しいキー送信方法を使用させることもできます。



22


昔の質問ですが、余分なコードを必要としない答えを見つけました。

テキストボックスの*自動補完*を有効にすると、CTRL-Backspaceは必要に応じて動作するはずです。

キャレットの左側にある単語全体をCtrl + Backspaceで削除することは、オートコンプリートハンドラの 'rogue feature'のようです。 そのため、オートコンプリートを有効にするとこの問題が解決します。

 — --

オートコンプリート機能を有効にするには、「+ AutoCompleteMode 」と「 AutoCompleteSource 」を好きなものに設定します(例えば、「 Suggest 」と「 RecentlyUsedList +」)


7


ProcessCmdKeyのオーバーライドはうまく機能しますが、主にSendWaitの使用はキーストロークを模倣するため、Ctrl Backspaceの繰り返しに1回だけに制限されています。バックスペースキーが押されています。 オーバーライドのキーストロークを記録すると、実際には押されたことのない追加のキーのコレクションが見つかります。

別の方法は、ProcessCmdKeyオーバーライドでテキストボックスの外観を明示的に管理し、それ以上システムにキーを送信しないことです。 これはCtrl Deleteにも簡単に適用できます。

Ctrl Backspaceの動作の一般的な「停止点」をいくつか含め、RegExではなくswitchステートメントを使用しました。 彼らは十分にきれいに感じることはありません、そして私は通常キャラクターを見逃してしまう

私のコードに問題があるようでしたら、ぜひ私にお知らせください。 まだこの難問に惑わされている人のために頑張ってください!

TextBoxEx:TextBox {protected override bool ProcessCmdKey(Ref Message msg、Keys keyData){if(keyData ==(Keys.Back | Keys.Control)){(int i = this.SelectionStart  -  1; i> 0; i--){switch(Text.Substring(i、1)){// case "":case ";":case "、":case "/":case \\ "が欲しいストップポイントを設定する:Text = Text.Remove(i、SelectionStart  -  i); SelectionStart = i; trueを返します。 case "\ n":Text = Text.Remove(i  -  1、SelectionStart  -  i); SelectionStart = i; trueを返します。 Clear(); //停止点に到達したことがない場合は、テキストボックス全体が空白になり、trueが返されます。 } else {return base.ProcessCmdKey(ref msg、keyData);} }}}


6


カスタムのKeyDownイベントまたはKeyPressイベントがないと可能であるかどうかはわかりませんが、次のコードは機能します。

private void textBox1_KeyDown(オブジェクト送信側、KeyEventArgs e){if((e.KeyCode == Keys.Back)


3


これは私が使っていたものです、それはまた複数行のテキストボックスを扱います

private void HandleCtrlBackspace_KeyDown(オブジェクト送信側、KeyEventArgs e){switch(e.KeyData){case(Keys.Back | Keys.Control):e.SuppressKeyPress = true; TextBox textbox =(TextBox)送信者。 int i; if(textbox.SelectionStart.Equals(0)){return; int space = textbox.Text.LastIndexOf( ''、textbox.SelectionStart  -  1); int line = textbox.Text.LastIndexOf( "\ r \ n"、textbox.SelectionStart  -  1); if(space> line){i = space; } else {i =行; } if(i> -1){while(textbox.Text.Substring(i  -  1、1).Equals( '')){if(i.Equals(0)){break;} }           私 - ; textbox.Text = textbox.Text.Substring(0、i)textbox.Text.Substring(textbox.SelectionStart); textbox.SelectionStart = i;そうでなければ(i.Equals(-1)){textbox.Text = textbox.Text.Substring(textbox.SelectionStart);破る; }}


2


これはあなたが行く方法です:)

private void textBox1_KeyPress(object sender、KeyPressEventArgs e){// ctrl bcksp if(e.KeyChar == 127){//最後の単語でない場合{//最後の単語のフォームリストを削除して、まとめて戻す(ラムダが大好きです) .Aggregate((a、b)=> a "" b); //選択範囲を最後に設定しますtextBox1.SelectionStart = textBox1.Text.Length;それ以外の場合(textBox1.Text.Split( '').Count()== 1){textBox1.Text = ""; }}}


2


これはうまくいきます:

static Regex RegExWholeWord = new Regex(@ "(\ r \ n | [^ A-Za-z0-9_ \ r \ n]?| \ w?)* $"、RegexOptions.Compiled);

キーダウンでは、

var m = RegExWholeWord.Match(textbox.Text、0、textbox.SelectionStart); if(m.Success){textbox.Text = textbox.Text.Remove(m.Index、m.Length); textbox.SelectionStart = m.Index; }


1


正規表現はこれのために作られました。 これを使って。

private void TextBox_KeyDown(オブジェクト送信側、KeyEventArgs e){TextBox box =(TextBox)送信側; if(e.KeyData ==(Keys.Back | Keys.Control)){if(!box.ReadOnly

private void RemoveWord(TextBox box){文字列text = Regex.Replace(box.Text.Substring(0、box.SelectionStart)、@ "(^ \ W)?\ w * \ W * $"、 ""); box.Text = text box.Text.Substring(box.SelectionStart); box.SelectionStart = text.Length; }


0


私はC#ではなくVBで答えています。私はVBでこの解決策を探していましたが、見つけることができませんでした、しかしこれらのC#の応答は私がそれを解決するのを助けました:-D

モジュール内にこのサブを作成する

Public Sub ctrl_bksp(ByRef t As TextBox)整数としてのディメンション= t.SelectionStart整数としてのディム= t.SelectionLength整数としてのディム= t.TextLength

'//選択範囲の両側を分割する開始文字列= Strings.Left(t.Text、tl  - (tl  -  ss))Dim strPost文字列= Strings.Right(t.Text、tl  -  ss  -  sl)

'//整数としてStrPreの最後のスペースの位置を取得= Strings.InStrRev(RTrim(strPre)、 "")

strPre = Strings.Left(strPre、s)

t.Text = strPre

その後、任意のテキストボックスのKeyPressイベント内からこのsubを呼び出すことができます。

プライベートSub Textbox1_KeyPress(Objectを送信者、System.Windows.Forms.KeyPressEventArgsを処理)Textbox1.KeyPressの選択ケースe.KeyCharのケースChr(127) '// Ctrl Backspace e.Handled = True Callサブ

これは、選択範囲が文字列内のどこにあるか、テキストが選択されているかどうかに関係なく機能し、壮大に反応します。


0


https://stackoverflow.com/users/2121596/dwf[DWF]およびhttps://stackoverflow.com/users/1006021/giangurgolo[giangurgolo]、ご提供いただきありがとうございます。 それの洗練されたバージョンの下に。 これは `ComboBox`も考慮していることに注意してください。それは` TextBox`と全く同じ問題を抱えているからです。 ショートカットは `TextBox`や` ComboBox`の設定が許す場合にのみ有効であることにも注意してください。

TextBoxEx:

パブリッククラスTextBoxEx:TextBox {protected override bool ProcessCmdKey(Ref Message msg、Keys keyData){//注意:// ComboBoxEx.ProcessCmdKey()にも同様のコードが存在します。 //ここでの変更はそこでも適用される必要があるかもしれません。

if(ShortcutsEnabled){if(keyData ==(Keys.Control | Keys.Back)){if(!ReadOnly){if(SelectionStart> 0){int i =(SelectionStart  -  1);}

//空白を削除します。if(char.IsWhiteSpace(Text、i))i =(StringEx.StartIndexOfSameCharacterClass(Text、i) -  1);

//前のマーカーを検索します。if(i> 0)i = StringEx.StartIndexOfSameCharacterClass(Text、i);そうでなければi = 0。 //上記のトリミングで-1になる可能性があるので、iを制限します。

//前のマーカーまたは先頭まで削除します。Text = Text.Remove(i、SelectionStart  -  i); SelectionStart = i;戻り値(true)。 } else {return(true);} //ホワイトボックスが配置されないように無視します。 else if(keyData ==(Keys.Control | Keys.A)){if(!ReadOnly)

return(base.ProcessCmdKey(ref msg、keyData)); }}

ComboxBoxEx:

パブリッククラスComboBoxEx:ComboBox {protected override bool ProcessCmdKey(Ref Message msg、Keys keyData){//注意:// TextBoxEx.ProcessCmdKey()にも同様のコードが存在します。 //ここでの変更はそこでも適用される必要があるかもしれません。

if(keyData ==(Keys.Control | Keys.Back)){if(DropDownStyle!= ComboBoxStyle.DropDownList){if(SelectionStart> 0){int i =(SelectionStart  -  1);

//空白を削除します。if(char.IsWhiteSpace(Text、i))i =(StringEx.StartIndexOfSameCharacterClass(Text、i) -  1);

//前のマーカーを検索します。if(i> 0)i = StringEx.StartIndexOfSameCharacterClass(Text、i);そうでなければi = 0。 //上記のトリミングで-1になる可能性があるので、iを制限します。

//前のマーカーまたは先頭まで削除します。Text = Text.Remove(i、SelectionStart  -  i); SelectionStart = i;戻り値(true)。 } else {return(true);} //ホワイトボックスが配置されないように無視します。 }}}

return(base.ProcessCmdKey(ref msg、keyData)); }}

文字列補助(例: 静的クラスStringEx):

///
/// Returns the start index of the same character class.
///
/// The  object to process.
/// The search starting position.
///
/// The zero-based index position of the start of the same character class in the string.
///
public static int StartIndexOfSameCharacterClass(s​​tring str、int startIndex){int i = startIndex;}

if(char.IsWhiteSpace(str、i))// 'IsControl'(、、...)と同様に 'IsSeparator'(Unicodeスペース/行/段落{//区切り文字)を含みます。 (/ * i * /; i> = 0; i--){if(!char.IsWhiteSpace(str、i))の場合(i 1);そうでなければ(char.IsPunctuation(str、i)){((/ * i * /; i> = 0; i--){if(!char.IsPunctuation(str、i))を返す)(i 1) ;そうでなければ(char.IsSymbol(str、i)){((/ * i * /; i> = 0; i--)に対する){if(!char.IsSymbol(str、i))return(i 1) ; else(for(/ * i * /; i> = 0; i--){if(char.IsWhiteSpace(str、i)|| char.IsPunctuation(str、i)|| char.IsSymbol(str、i) i))(i 1)を返す。 }}

(0)を返します。 }