DOBON.NET DOBON.NETプログラミング掲示板過去ログ

TextBoxのフォーマット指定

環境/言語:[VB.NET 2003]
分類:[.NET]

おはようございます。
質問攻めですみません、あのね です。

VB.NETでの開発を行うとき、TextBoxを使用することって
結構あるかと思います。
私も、沢山のTextBoxを扱いながら作業を進めています。

今回の質問は、
『TextBoxに、予めフォーマットの指定をしておくことは
 できないの??』
ということなのです。


 ・数値を入力するTextBox(txtNum)がある。
 ・txtNumの入力値を、"#,##0"のフォーマットで表示したい。
 ・このフォーマットを整える処理をリアルタイムで行いたい。
  (↑4桁目の数を入力すると同時に","が表示される)

・・・という処理を行いたいと思っているのですが、
TextBoxには、フォーマットを指定するプロパティってないですよね?
KeyPressイベントを拾い、都度、処理をかけようかとしたのですが、
それも上手くいきませんでした。
(力量不足かΣ(゚□゚*)!?)

この処理を行いたい部分(TextBox)が沢山あるので、
1つ、ユーザーコントロールを作ってしまおうかと思っていたのですが、
それ以前の問題で行き詰ってしまいました^^;

どなたか同じような処理をされている方がいらっしゃいましたら、
助言いただきたく・・・。

よろしくお願いいたします。
じゃんぬねっと です。

■No8832に返信(あのねさんの記事)
> VB.NETでの開発を行うとき、TextBoxを使用することって結構あるかと思います。
> 私も、沢山のTextBoxを扱いながら作業を進めています。

>  ・数値を入力するTextBox(txtNum)がある。
>  ・txtNumの入力値を、"#,##0"のフォーマットで表示したい。
>  ・このフォーマットを整える処理をリアルタイムで行いたい。
>   (↑4桁目の数を入力すると同時に","が表示される)

> ・・・という処理を行いたいと思っているのですが、
> TextBoxには、フォーマットを指定するプロパティってないですよね?
> KeyPressイベントを拾い、都度、処理をかけようかとしたのですが、
> それも上手くいきませんでした。
> (力量不足かΣ(゚□゚*)!?)

> この処理を行いたい部分(TextBox)が沢山あるので、
> 1つ、ユーザーコントロールを作ってしまおうかと思っていたのですが、
> それ以前の問題で行き詰ってしまいました^^;
> どなたか同じような処理をされている方がいらっしゃいましたら、
> 助言いただきたく・・・。

まさしくって感じのがありますが、こんなのとかお気に召しませんか? (^-^;)
http://f57.aaa.livedoor.jp/~jeanne/library/

> ----------------------------------------------------------------
 [Download] 入力文字を制限・書式を自動形成する TextBox
 [Download] 入力文字を制限・書式を自動形成する ComboBox
 [Download] ショートカット キーを実装した Button
> ----------------------------------------------------------------
いつも早いお返事、ありがとうございます。

>  [Download] 入力文字を制限・書式を自動形成する TextBox

おぉっ、こんな感じです!!
このコントロールの
  ExTextBox1.Format = "#,##0"
に近いものを実現しようとしています。
ということは・・・、私の力量不足及び調査不足ですね^ ^ ;

重ね重ね申し訳ないのですが、もし良ければ、
参考にソースの端っこを見せてもらえないでしょうか?
作成したユーザーコントロールは、今席を置いているチーム全体で
使うことになると思われます。
ので、参考にしつつ、チーム色に作りこみしたいと思ったのですが・・・。

/*
 もちろん、無理は言わないです。
 「実際にできるんだ」と分かっただけでも十分励みになりますので(`・ω・´)
*/
じゃんぬねっと です。こんにちは。

■No8835に返信(あのねさんの記事)
> 重ね重ね申し訳ないのですが、もし良ければ、
> 参考にソースの端っこを見せてもらえないでしょうか?

もちろん構いません。
あのページでも、ソースを公開しようと準備しているのですが、
これまた休日に限って忙しいので、全然できていません (^-^;)

> 作成したユーザーコントロールは、今席を置いているチーム全体で使うことになると思われます。
> ので、参考にしつつ、チーム色に作りこみしたいと思ったのですが・・・。

そうですね、その方がいいでしょう。

> もちろん、無理は言わないです。
> 「実際にできるんだ」と分かっただけでも十分励みになりますので(`・ω・´)

ん? VB.NET で宜しかったですか?
極力要らない部分は、削除しております。

Source Begin:--------------------------------------------------------------

''' ---------------------------------------------------------------------
''' <summary>
'''     書式設定や入力タイプなどを定義した TextBox コントロール クラス。
''' </summary>
''' ---------------------------------------------------------------------

Public NotInheritable Class ExTextBox
    Inherits System.Windows.Forms.TextBox

#Region " Define "

    ' プロパティ 変数
    Private _Format As String

#End Region

#Region " プロパティ − Format "

    ''' -----------------------------------------------------------------
    ''' <summary>
    '''     フォーカスを失った際の再フォーマットの書式を取得または設定します。
    ''' </summary>
    ''' -----------------------------------------------------------------
    <Description ("フォーカスを失った際の再フォーマットの書式です。"), _
     Category    ("追加定義プロパティ"), _
     DefaultValue(""), _
     ParenthesizePropertyName(True)> _
    Public Property Format() As String
        Get
            Return _Format
        End Get

        Set(ByVal Value As String)
            _Format = Value
        End Set
    End Property

#End Region

#Region "  イベント   − this :: Enter() "

    Private Sub ExTextBox_Enter(略) Handles MyBase.Enter
        Me.Text = GetReleaseFormatText(Me.Text, Me.Format)
        Me.SelectAll()
    End Sub

#End Region

#Region "  イベント   − this :: Leave() "

    Private Sub ExTextBox_Leave(略) Handles MyBase.Leave
        Me.Text = GetRestoreFormatText(Me.Text, Me.Format)
    End Sub

#End Region

Source End:----------------------------------------------------------------


以下の 2 点のメソッドを独自に組んで頂ければ良いのではないかと思われます。

 GetReleaseFormatText() メソッド ・・・ フォーマットを解放する (カンマを外したり、小数点外したり)
 GetRestoreFormatText() メソッド ・・・ フォーマットを設定する (カンマ区切りにしたり、小数点付けたり)


# 私がまだ .NET をやり始めたばかりに作ったソースで、
# ちょっと汚いかもしれませんが、その辺りはご留意ください。m(_ _)m
ありがとうございます_(._.)_

今のところ、TextBoxのTextChangedイベントの度にサブを呼ぶことで
解決することにしました。

↓-----------------------------------------------------------
  Private Sub Format_NumTextBox( ByVal strText As String, _
                  ByRef strRetText As String)

    strRetText = String.Format("{0:#,##0}", CLng(strText))
  End Sub


  Private Sub txt_Haba_TextChanged(...) Handles txt_Haba.TextChanged
     Dim strText As String

    Format_NumTextBox(txt_Haba.Text, strText)

    txt_Haba.Text = strText
    txt_Haba.SelectionStart = txt_Haba.TextLength
  End Sub
↑-----------------------------------------------------------

/*
 txt_Haba.SelectionStart = txt_Haba.TextLength
  →サブから戻った時にカーソルが左端にあったのを右端に移動させる為です。
   (右詰のBoxなので・・・)
*/

あ・・・Functionにしたら良かったのか・・・ (ゴソゴソ


>Me.Text = GetReleaseFormatText(Me.Text, Me.Format)
の引数から、こんな感じかな・・・と思ったのですが、
[Format]の部分を文字型の変数(strFormat = "#,##0")で渡したら、
上手く動いてくれませんでした。
何か一工夫いるのかな・・・ (ゴソゴソゴソ

コレを基に、色々と触ってみます。
参考になるソースを教えていただき、ありがとうございました。



・・・・と安心したところ続け様で申し訳ないのですが、
いくつか質問してもよろしいでしょうか(汗

<1>
 txtHaba
 [ 1,234] となっている状態で、
  ↑この時、txtHaba.Text = "1,234" ですよね?

 5桁目となる数を打ち込むと、ありがたくも普通に、
 [ 12,345] となりますが、これってなぜなのでしょう?

 "1,234"を引数として渡しているはずなのに、Formatで変換が行われる時には
 カンマはないものとして処理されています。
 数値型に変換すると、自動的に","をどけてくれるのでしょうか??


<2>
 txt_Haba_TextChanged の中で、再帰処理が発生してしまいます。
 これが起きる原因には納得しているのですが、何か対処法がないかなと
 思いまして・・・。
 
 /*
  txt_Haba.Text = strText
  で戻り値をTextBoxに代入する時に、再びTextが変化するから・・・
  だと考えてます。
 */


長くなってしまい、すみません。
妙な部分があったら突っ込んでください_(._.)_
じゃんぬねっと です。

■No8837に返信(あのねさんの記事)
> 今のところ、TextBoxのTextChangedイベントの度にサブを呼ぶことで
> 解決することにしました。

それは、カスタムコントロールのお話ですか?
よもや、個別にイベントを実装しているわけではないですよね?

> txt_Haba.SelectionStart = txt_Haba.TextLength
> →サブから戻った時にカーソルが左端にあったのを右端に移動させる為です。
> (右詰のBoxなので・・・)

これだと、最後の位置以外から文字を入力などすると、違和感のある、
いや〜な感じの GUI になるような気がするのですが...
カレット位置を復元したいのならば、細工をする前のカレット位置を保存しておき、
細工後との文字列数を比較して、その差分で復元してあげるべきですね。

> > Me.Text = GetReleaseFormatText(Me.Text, Me.Format)
> の引数から、こんな感じかな・・・と思ったのですが、
> [Format]の部分を文字型の変数(strFormat = "#,##0")で渡したら、
> 上手く動いてくれませんでした。
> 何か一工夫いるのかな・・・ (ゴソゴソゴソ

この辺りも公開しちゃった方がよかったかしら...
ちなみに、GetReleaseFormatText() は、Static なメソッドです。

> <1>
>  txtHaba
>  [ 1,234] となっている状態で、
>   ↑この時、txtHaba.Text = "1,234" ですよね?
>
>  5桁目となる数を打ち込むと、ありがたくも普通に、
>  [ 12,345] となりますが、これってなぜなのでしょう?

>  "1,234"を引数として渡しているはずなのに、Formatで変換が行われる時には
>  カンマはないものとして処理されています。
>  数値型に変換すると、自動的に","をどけてくれるのでしょうか??

内部的には、Format 関数は数値の形式であれば正しく変換してくれます。
数値化のルールとしては、

 ・「0」〜「9」の数字であること。
 ・「+」「-」が先頭にしかないこと。
 ・「,」は途中にいくつあってもよい。
 ・「.」は 1 つのみ存在可能

といった感じになります。

> <2>
>  txt_Haba_TextChanged の中で、再帰処理が発生してしまいます。
>  これが起きる原因には納得しているのですが、何か対処法がないかなと
>  思いまして・・・。

簡単に言うならば、フラグを設ければ済むのではないかと。

それを解決したとしても TextChanged() イベントでこのような校正を行うと、
チラツキが発生するため、もっと前の段階で Hide するようにすべきかと思います。

まあ、その前に、TextChanged() イベントで入力中のテキストを勝手に校正するのは、
ユーザーのアクセシビリティの低下に繋がり、ユーザ フレンドリでないと思うのです。

通常は、
 Enter() イベントで書式を解除 (例 :「12,345.00」→「12345」)
 Leave() イベントで書式を設定 (例 :「12345」→「12,345.00」)
となるのが望ましいのです。

> 長くなってしまい、すみません。
> 妙な部分があったら突っ込んでください_(._.)_

すいません、結構突っ込んでしまいました。(^-^A)

# 今回の仕様、ユーザの立場で再度検討して頂けませんでしょうか?
>すいません、結構突っ込んでしまいました。(^-^A)
私こそ、ちっとも良い生徒でなくてごめんなさい_(._.)_

ずっと、
 Enterイベントは、TextChagedイベントと(ほぼ)同じ。
 Leaveイベントは、LostFocusイベントと(ほぼ)同じ。
だと、語感から勝手に想像して使っていました。
調べてみると、実は全く違うものだったのですね。
悪い癖です・・・。

ので、最初に公開していただいたソースを基に大幅に作り変え、
ユーザーコントロールとして上手く動くことは確認できました。

ところが、ユーザーコントロールって・・・、Formに設置した後で
ユーザーコントロール内(?)のTextBoxのサイズを変えることって
できないのですね(´・ω・`)

┌------------------------------------------------
|frmMain

|   ↓ユーザーコントロール(UC_tstNum)を設置
|  ┌-------------------------------┐
|  | [ txt_Num ]        |
|  |  ↑ユーザーコントロール内のTextBox
|  └-------------------------------┘


・・・とある時、frmMain側からtxt_Numの巾等を変更したいのです。

(ここまで書いて、ふと思いついたので試してみる・・・)


できましたΣ(゚□゚*)!

(せっかく?書いたので、勘違いも残します;;)

  ユーザーコントロール(UC_tstNum)
 ┌-------------------------------┐
 | [ txt_Num ]        |
 |  ↑ユーザーコントロール内のTextBox
 └-------------------------------┘

txt_NumのAnchorを指定してあげるだけでした(-"-;)


>今回の仕様・・・
4桁目を入力すると同時にカンマが・・・というのを、あちこちで
見かけるので、そうした方が良いのかな?と思って、
無理矢理、上のような処理にしていました。
それで使いにくかったりエラーの原因になるのであれば、
考える間もなく、コチラで(`・ω・´)

>内部的には、Format 関数は数値の形式であれば正しく変換してくれます。
そうなのですか!
・・ということは、
 >>数値型に変換すると、自動的に","をどけてくれる
のではなくて、あくまでも、
 >>[Format関数] が処理してる
ことになるのかな・・??


ユーザーコントロール完成まで、もう少しです・・・。
じゃんぬねっと です。

■No8841に返信(あのねさんの記事)
> 私こそ、ちっとも良い生徒でなくてごめんなさい_(._.)_

いえいえ、いつもご丁寧にありがとうございます。

> Enterイベントは、TextChagedイベントと(ほぼ)同じ。
> Leaveイベントは、LostFocusイベントと(ほぼ)同じ。
> だと、語感から勝手に想像して使っていました。
> 調べてみると、実は全く違うものだったのですね。
> 悪い癖です・・・。

ちなみに、GotFocus() イベントと、LostFocus() イベントは低水準イベントなので、
お使いにならないようにしてくださいね。

> ユーザーコントロール完成まで、もう少しです・・・。

えーと... ユーザーコントロールではなく、カスタムコントロールでやりましょう。
私が、■No8836 で書いた

> ---------------------------------------------
Public NotInheritable Class ExTextBox
  Inherits System.Windows.Forms.TextBox
> ---------------------------------------------

を見て頂ければ、わかるかと思います。

# ユーザーコントロールだと、まあ、カスタムコントロールに比べて、
# コンテナを使っている分、重いですし、それとバグの温床になりやすいので...
お返事遅くなり申し訳ありません_(._.)_

駆け足でなんなのですが、先日、進めていたものが
ようやく完成しました^^

いつもながら沢山のアドバイス、ありがとうございました。
解決済み!
じゃんぬねっと です。

■No8880に返信(あのねさんの記事)
> お返事遅くなり申し訳ありません_(._.)_
> 駆け足でなんなのですが、先日、進めていたものが
> ようやく完成しました^^
> いつもながら沢山のアドバイス、ありがとうございました。

うーん、System.Windows.Forms.TextBox コントロールを継承した
「カスタム コントロール」で実装したんでしょうか...
その辺りのフィードバックがなかったもので、少々心配しております。

# 「ユーザ コントロール」でやるべきことではないと思いますので。
# 余計な心配ならば良いのですが...
解決済み!
ありがとうございます。

少し焦り気味で返答を書くタイミングを逃してしまって事と、
「カスタムコントロール」と「ユーザーコントロール」の違いや
作成方法について調べていたら、時間がかかってしまいました^ ^;

お心遣いありがとうございます。
アドバイスいただいたとおり、カスタム・・で作成しています。


また、これからも別の質問等するかと思います。
(寧ろ、します。決定です。)
その折は、よろしくお願いします(^-^*)
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板