PDA

View Full Version : سوال: TextBox برای اعداد



mehdi_79
جمعه 15 دی 1391, 09:05 صبح
من برای وارد کردن الزامی عدد در TextBox از کد هی زیر استفاده می کنم



Dim textboxNumber As Boolean = False

Private Sub TextBox_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox.KeyDown
textboxNumber = False
If e.KeyCode < Keys.D0 OrElse e.KeyCode > Keys.D9 Then
If e.KeyCode < Keys.NumPad0 OrElse e.KeyCode > Keys.NumPad9 Then
If e.KeyCode <> Keys.Back Then
textboxNumber = True
End If
End If
End If
End Sub

Private Sub TextBox_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox.KeyPress
If textboxNumber = True Then
e.Handled = True
End If
End Sub



با توجه به احتیاج زیاد به این نوع TextBox می خواستم با ساختن آن در همه جای برنامه استفاده کنم
لطفا مرا راهنمایی کنید

ghayour
جمعه 15 دی 1391, 10:10 صبح
سلام دوست عزیز

برای اینگونه کارها یا باید از کامپوننت ها استفاده کنی یا اینکه خودت یک کاستوم کنترل بسازی.
من الآن یک کاستوم کنترل با کدهای خودت نوشتم که امیدوارم بدردت بخوره.
فقط عجله داشتم و یادم نبود که از کجا میشه به صورت dll در آوردش.

ضمنا کد دیگری هم که من قبلا استفاده کردم این هستش:
Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
If (Char.IsDigit(e.KeyChar) Or e.KeyChar = Convert.ToChar(Keys.Back)) Then
e.Handled = False
Else
e.Handled = True
End If
End Sub

ولی مشکل این کد و کد شما اینه که هر دو با کپی پست کردن میشه حروف رو وارد تکست باکس کرد.

اینم پروژه:

فرید نجفلو
جمعه 15 دی 1391, 11:18 صبح
سلام
اینکه از کنترل رو سفرشی کنیم یکی از بهترین روش ها برای این کارهاست فقط روشی که دوستمون دادن رو تایید می کنم فقط دو تا مورد کوچیک داره
* کد شما رو میشه دور زد! برای امتحان یک متن غیر عددی رو کپی و داخل کنترل تون با راست کلیک پیست کنید
* کنترل از عمومیت خارج شده به طوری که برای کار های عددی خوبه ولی برای کارهای متنی باید از یک تکست باکس معمولی استفاد کرد

Imports System.ComponentModel
Public Class fnTextBox
Inherits TextBox

Private LastText As String = ""

<Description("ورودی فقط عددی"), DefaultValue(False)> _
Public Property NumericOnly As Boolean = False

Protected Overrides Sub OnKeyPress(e As System.Windows.Forms.KeyPressEventArgs)
If Me.NumericOnly AndAlso Not (Char.IsDigit(e.KeyChar) OrElse Char.IsControl(e.KeyChar)) Then
e.KeyChar = Nothing
End If
MyBase.OnKeyPress(e)
End Sub

Protected Overrides Sub OnTextChanged(e As System.EventArgs)
MyBase.OnTextChanged(e)
If Me.Text <> "" AndAlso Me.NumericOnly AndAlso Not IsNumeric(Me.Text) Then
If IsNumeric(LastText) Then
Me.Text = LastText
Else
Me.Text = ""
End If
Me.Select(Me.Text.Length, 0)
End If
LastText = Me.Text
End Sub
End Class


این کنترل هم برای متن و هم برای عدد کار می کنه فقط کافیه تو پنجره Properties مقدار NumericOnly رو ست کنید
شما می تونید هر جا که کادر متنی نیاز بود از همین استفاده کنید یکی از مزایای این عمومیت هماهنگ کردن برنامست مثلا اگه اواسط کار خواستید تمام متن های شما وقتی فعال شدن زنگ پس زمینشون عوض شه فقط با گذاشتن کد تو این قسمت کار تمومه!

تو برنامه نویسی سعی کنید بلند نظر باشید و نیاز های فردا رو هم در نظر بگیرید و فقط به فکر مشکل فعلی نباشید

mehdi_79
جمعه 15 دی 1391, 18:58 عصر
با تشکر از پاسخ های مفید شما با توجه به اینکه من VB 2005 استفاده می کنم اگر معادل این کد را بگذارید ممنون می شوم

<Description("ورودی فقط عددی"), DefaultValue(False)> _
Public Property NumericOnly As Boolean = False

ghayour
جمعه 15 دی 1391, 19:14 عصر
البته من با VB 2005 کار نکردم(به نظر من فرقی نکنه) اما احتمال میدهم که شما Imports System.ComponentModel را تایپ نکرده‌اید و ضمنا این که این کدی آقای نجفلو دادن رو بجای کدی(کد کامپوننت) که در اون پروژه برای شما گذاشتم بگذارید و تکست باکس ها رو پاک کنید برنامه و Build کنید و آنگاه می توانید از کاستوم کنترل جدید استفاده کنید.

mehdi_79
جمعه 15 دی 1391, 19:43 عصر
این کد جواب داد


Private _NumericOnly As Boolean = False

Public Property NumericOnly() As Boolean
Get
Return _NumericOnly
End Get
Set(ByVal value As Boolean)
_NumericOnly = value
End Set
End Property

فقط نتظیم Description را نمی دونم
در ضمن اگر تنظیم سایر خصوصیت های text box از قبیل NumTextBox1.TextAlign = HorizontalAlignment.Center و یا فونت را بفرمایید ممنون می شم

یه سوال دیگه : چطور میشه text box ها را بدون حذف و دوباره اضافه کردن کنترل جدید به کلاس جدید تبدیل کرد

فرید نجفلو
جمعه 15 دی 1391, 20:31 عصر
سلام مجدد
لطفا کد ها رو داخل تگ ها بنویسید (روی http://barnamenevis.org/images/editor/vb.gif یا مورد متانسب روی نوار ادیتور کلیک کنید و بین اون کد های اضافه شده بنویسید)



با تشکر از پاسخ های مفید شما با توجه به اینکه من VB 2005 استفاده می کنم اگر معادل این کد را بگذارید ممنون می شوم

<Description("ورودی فقط عددی"), DefaultValue(False)> _
Public Property NumericOnly As Boolean = False



خط اول Attribute ها هستن که اگه نباشن هم مشکلی نداره ، این دو مورد تو قسمت دیزاینر کمک می کنه. در صورت استفاده هم همینطوری به بالای تعریف جدیدتون اضافه میشه (تعریف خود پروپرتی نه متغیر محلیش مکه با _ شروع شده)

خط دوم تعریف پروپرتی به روش Ipmplicit هست که از 2010 اضافه شده و اجازه می ده پروپرتی های عادی رو به صورت تک خطی تعریف کنید(کد کمتر ، خوانا تر و نوشتن راحت تر)


یه سوال دیگه : چطور میشه text box ها را بدون حذف و دوباره اضافه کردن کنترل جدید به کلاس جدید تبدیل کرد
در این مورد پیشنخاد من ReplaceAll هست
پنجره Replace رو باز کنید (Ctrl+H) به این صورت در سطح راه حل (Entire Solution) جایزگزین کنید (دکمه ReplaceAll)
به فرض نام کلاس جدید fnTextbox باشه

As Textbox با As fnTextbox
New Textbox با New fnTextbox

فکر کنم همین کافی باشه
فقط قبل از این کار یه کپی پشتیبان بگیرید

ghayour
دوشنبه 18 دی 1391, 11:43 صبح
چجور کدی توی این کنترلی که درست کردین بنویسیم که اگه Numeric Only فعال بود عدد داخل تکست باکس از یک حدی بیشتر نشه(یعنی از پروپرتی جدیدی که ساختیم مثلا با نام MaxNumber بیشتر نشه البته اگر مقدار صفر داشت غیرفعال باشه). منظورم طول عدد نیست.
مثل ساعت که نباید از 24 بیشتر بشه.

asghar2008
دوشنبه 18 دی 1391, 11:55 صبح
چجور کدی توی این کنترلی که درست کردین بنویسیم که اگه Numeric Only فعال بود عدد داخل تکست باکس از یک حدی بیشتر نشه(یعنی از پروپرتی جدیدی که ساختیم مثلا با نام MaxNumber بیشتر نشه البته اگر مقدار صفر داشت غیرفعال باشه). منظورم طول عدد نیست.
مثل ساعت که نباید از 24 بیشتر بشه.
سلام

می تونید با یه If ساده عدد داخل Textbox رو کنترل کنید.

ghayour
دوشنبه 18 دی 1391, 12:05 عصر
درسته اما می خواهم راه کوتاهتری و اصولی‌تری باشه مثلا توی MaxNumber عدد 59 رو نوشته باشه آنوقت اگه عدد 6 رو نوشت خاصیت MaxLenght اون 1 بشه اما ممکنه توی MaxNumber عدد 24 رو نوشته باشه.

asghar2008
دوشنبه 18 دی 1391, 12:22 عصر
خاصیت Maxlenght تکست باکس، برای مشخص کردن تعداد کارکتر های مجاز است.
حالا شما می خواهید عدد داخل Textbox از 24 بیشتر نشه.

برای این کار Maxlenght =2 قرار بدین و در خاصیت Textchange تکست باکس یه شرط بذارید.

If TextBox1.Text > 24 Then
MsgBox("این عدد غیر مجاز است")
End If

امیدوارم منظور شما رو متوجه شده باشم.

ghayour
دوشنبه 18 دی 1391, 12:43 عصر
منظورم این نیست که پیامی بده یا اگه بزرگتر بود اونرو صفرکنه می‌خوام کاستوم کنترل رو جوری بنویسم که اگه داخل MaxNumber (پروپرتی جدید) مقدار خاصی داده شده بود دیگه بیشتر از اون نگذاره بنویسم یعنی مثلا اگه 24 نوشته شده بود، داخل تکست باکس 3 رو نوشتم نگذاره عدد بعدی رو بنویسم یعنی هرچه که اعداد رو میزنم کارنکنه مثل وقتی که نمی گذاره حروف نوشته بشه. یا اگه داخل تکست باکس 2 رو نوشتم برای رقم دومش فقط کیبرد روی اعداد 0 تا 4 کار کنه و نشه بیشتر از اون رو نوشت تا از 24 بیشتر نشه.

asghar2008
دوشنبه 18 دی 1391, 13:37 عصر
فک کردم تو خود کنترل تکست باکس VS میخوای این کارو انجام بدین.اخه شما نوشتین 24 منم فکرکردم عدد بیست و چهار!! منظور شما 2 و4 بوده.
متاسفانه با طراحی Usercontrol زیاد کارنکردم.
اما یه پیشنهاد:
اون موقع باید در Property جدید (MaxNumber) یه متغیر min و یه متغیر max در نظر بگیرید.وبا If مشخص کنید که اگر عدد مابین و مساوی min و max بود.عمل مقدار دهی انجام شود.

ghayour
دوشنبه 18 دی 1391, 14:18 عصر
اخه شما نوشتین 24 منم فکرکردم عدد بیست و چهار!! منظور شما 2 و4 بوده.

اتفاقا منظورم 24 بوده.


اما یه پیشنهاد:
اون موقع باید در Property جدید (MaxNumber) یه متغیر min و یه متغیر max در نظر بگیرید.وبا If مشخص کنید که اگر عدد مابین و مساوی min و max بود.عمل مقدار دهی انجام شود.
فهمیدم چی گفتی. یعنی حد پایین هم داشته باشه مثلا بین 11 و 24 اما فکر کنم این با چیزی که من میخوام تداخل ایجاد کنه.


چجور کدی توی این کنترلی که درست کردین بنویسیم که اگه Numeric Only فعال بود عدد داخل تکست باکس از یک حدی بیشتر نشه(یعنی از پروپرتی جدیدی که ساختیم مثلا با نام MaxNumber بیشتر نشه البته اگر مقدار صفر داشت غیرفعال باشه). منظورم طول عدد نیست.
مثل ساعت که نباید از 24 بیشتر بشه.

منظورم این نیست که پیامی بده یا اگه بزرگتر بود اونرو صفرکنه می‌خوام کاستوم کنترل رو جوری بنویسم که اگه داخل MaxNumber (پروپرتی جدید) مقدار خاصی داده شده بود دیگه بیشتر از اون نگذاره بنویسم یعنی مثلا اگه 24 نوشته شده بود، داخل تکست باکس 3 رو نوشتم نگذاره عدد بعدی رو بنویسم یعنی هرچه که اعداد رو میزنم کارنکنه مثل وقتی که نمی گذاره حروف نوشته بشه. یا اگه داخل تکست باکس 2 رو نوشتم برای رقم دومش فقط کیبرد روی اعداد 0 تا 4 کار کنه و نشه بیشتر از اون رو نوشت تا از 24 بیشتر نشه.

asghar2008
دوشنبه 18 دی 1391, 14:57 عصر
اگه داخل تکست باکس 2 رو نوشتم برای رقم دومش فقط کیبرد روی اعداد 0 تا 4 کار کنه و نشه بیشتر از اون رو نوشت تا از 24 بیشتر نشه.

این 0 تا 4 منو:گیج: کرد.

فرید نجفلو
دوشنبه 18 دی 1391, 15:50 عصر
سلام
دوست عزیز دیگه وقتی اضل کد رو دارید این چیزی که می خواید نباید سخت باشه
سعی کنید بیشتر تلاش کنید

کد اصلاح شده:

Imports System.ComponentModel
Public Class fnTextBox
Inherits TextBox

Private LastText As String = ""

<Description("ورودی فقط عددی"), DefaultValue(False)> _
Public Property NumericOnly As Boolean = False


<Description("حد بالای مقدار وارد شده در حالت عددی"), DefaultValue(Integer.MaxValue)> _
Public Property MaxNumValue As Integer = Integer.MaxValue

Protected Overrides Sub OnKeyPress(e As System.Windows.Forms.KeyPressEventArgs)
If Me.NumericOnly AndAlso Not (Char.IsDigit(e.KeyChar) OrElse Char.IsControl(e.KeyChar)) Then
e.KeyChar = Nothing
End If
MyBase.OnKeyPress(e)
End Sub

Protected Overrides Sub OnTextChanged(e As System.EventArgs)
MyBase.OnTextChanged(e)
If Me.Text <> "" AndAlso Me.NumericOnly AndAlso Not IsNumeric(Me.Text) Then
If IsNumeric(LastText) Then Me.Text = LastText Else Me.Text = ""
Me.Select(Me.Text.Length, 0)
End If

If NumericOnly AndAlso IsNumeric(Me.Text) AndAlso Val(Me.Text) > MaxNumValue Then
If IsNumeric(LastText) Then Me.Text = LastText Else Me.Text = ""
Me.Select(Me.Text.Length, 0)
End If

LastText = Me.Text
End Sub
End Class

asghar2008
دوشنبه 18 دی 1391, 16:14 عصر
چرا از TextBox خطا میگیره ؟
اینم عکسش :
98003

ghayour
دوشنبه 18 دی 1391, 17:14 عصر
چرا از TextBox خطا میگیره ؟
اینم عکسش :
98003
روی راهنمایی خطاش کلیک کن و بعد اولیش رو کلیک کن تا تبدیل به تکست باکس بشه.

asghar2008
دوشنبه 18 دی 1391, 17:44 عصر
هر کاری میکنم خطا میگیره

ghayour
دوشنبه 18 دی 1391, 18:19 عصر
اشتباه من این بود که متغیر LastText رو نمی دونستم چیه و در کدهام از KeyChar یا Handled استفاده می کردم. از شما خیلی متشکرم.
این کد رو کمی اصلاح کردم تا اگر مقدار آن صفر بود پروپرتی MaxNumValue غیر فعال باشد.

ghayour
دوشنبه 18 دی 1391, 18:40 عصر
راستی می خواستم بپرسم اگه این کنترل رو با استفاده از TextBoxX کامپوننت DevComponents بنویسم بعدا مشکلی به وجود نمیاد؟ (چون بشه از امکانات اون هم استفاده کرد):متفکر:

فرید نجفلو
دوشنبه 18 دی 1391, 20:18 عصر
راستی می خواستم بپرسم اگه این کنترل رو با استفاده از TextBoxX کامپوننت DevComponents بنویسم بعدا مشکلی به وجود نمیاد؟ (چون بشه از امکانات اون هم استفاده کرد):متفکر:

مشکلی نیست ، در واقع من این کد ها رو با تسکت باکس جانوس استفاده می کنم

mehdi_79
دوشنبه 18 دی 1391, 20:20 عصر
چطور میشه کدی اضافه کرد که هنگام تایپ عدد را با جدا کننده 1000 نمایش دهد مثل 2,521,621

ghayour
دوشنبه 18 دی 1391, 23:22 عصر
چطور میشه کدی اضافه کرد که هنگام تایپ عدد را با جدا کننده 1000 نمایش دهد مثل 2,521,621
اگه جستجو کنی زیاد پیدا می‌کنی مثل:
http://barnamenevis.org/showthread.php?150399-%D8%AC%D8%AF%D8%A7-%D9%83%D8%B1%D8%AF%D9%86-%D8%B3%D9%87-%D8%B1%D9%82%D9%85-%D8%B3%D9%87-%D8%B1%D9%82%D9%85-%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF-%D8%AF%D8%B1-%D8%AA%D9%83%D8%B3-%D8%A8%D8%A7%D9%83%D8%B3

اگه منظورت توی کاستوم کنترل بود که پست آقای نجفلو رو نگاه کنید.(پست پایینی)

ضمنا اگه هر کی از این کنترل استفاده میکنه یا خوشش میاد حتما از آقای نجفلو تشکر کنه.(با زدن دکمه "تشکرکردن")

فرید نجفلو
سه شنبه 19 دی 1391, 00:52 صبح
کد اصلاح شده و دقیقتر

Imports System.ComponentModel
Public Class NumericTextBox
Inherits TextBox

''' <summary>
''' آخرین مقداری که در تکست باکس به صورت مجاز وارد شده است
''' </summary>
''' <remarks></remarks>
Private LastText As String = ""

Private _NumericOnly As Boolean = False
<Description("ورودی فقط عددی"), DefaultValue(False)> _
Public Property NumericOnly As Boolean
Get
Return _NumericOnly
End Get
Set(value As Boolean)
_NumericOnly = value
OnTextChanged(Nothing)
End Set
End Property

Public _MaxNumValue As Integer = 0
<Description("حد بالای مقدار وارد شده در حالت عددی. درصورتی که این مقدار برابر 0 باشد این پروپرتی غیرفعال خواهد بود"), DefaultValue(0)> _
Public Property MaxNumValue As Integer
Get
Return _MaxNumValue
End Get
Set(value As Integer)
_MaxNumValue = value
OnTextChanged(Nothing)
End Set
End Property


Public _SeparatNumber As Boolean = False
<Description("جدا کردن سه رقمی اعداد"), DefaultValue(0)> _
Public Property SeparatNumber As Boolean
Get
Return _SeparatNumber
End Get
Set(value As Boolean)
_SeparatNumber = value
OnTextChanged(Nothing)
End Set
End Property


Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
If Me.NumericOnly AndAlso Not (Char.IsDigit(e.KeyChar) OrElse Char.IsControl(e.KeyChar)) Then
e.KeyChar = Nothing
End If
MyBase.OnKeyPress(e)
End Sub

Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
MyBase.OnTextChanged(e)
If Me.Text <> "" AndAlso Me.NumericOnly AndAlso Not IsNumeric(Me.Text) Then
If IsNumeric(LastText) Then Me.Text = LastText Else Me.Text = ""
Me.Select(Me.Text.Length, 0)
End If

If NumericOnly AndAlso IsNumeric(Me.Text) AndAlso Val(Me.Text) > MaxNumValue AndAlso MaxNumValue <> 0 Then
If IsNumeric(LastText) Then Me.Text = LastText Else Me.Text = ""
End If

If NumericOnly AndAlso SeparatNumber AndAlso IsNumeric(Me.Text) Then
Me.Text = FormatNumber(Me.Text, 0)
End If
Me.Select(Me.Text.Length, 0)

LastText = Me.Text
End Sub
End Class

ghayour
سه شنبه 19 دی 1391, 12:35 عصر
دلیل اینکه بعضی جاها علامت "_" رو میذارن چیه؟
مثلا من اینرو بدون این علامت امتحان کردم باز هم درست کارکرد.
<Description("ورودی فقط عددی"), DefaultValue(False)>

دلیل این کد چیه توی کدهای بالا: :متفکر:
OnTextChanged(Nothing)

ضمنا چرا میگید این کد دقیق تره؟ :متفکر:

اگه بخواهیم یک پروپرتی به صورت زیر مجموعه یک پروپرتی دیگه بنویسیم باید چیکار کنیم(اصلا اینجوری میشه؟)؟ (مثل فونت که زیر مجموعه داره؟)

فرید نجفلو
سه شنبه 19 دی 1391, 17:13 عصر
دلیل اینکه بعضی جاها علامت "_" رو میذارن چیه؟
مثلا من اینرو بدون این علامت امتحان کردم باز هم درست کارکرد.
1
<Description("ورودی فقط عددی"), DefaultValue(False)>




تا قبل از 2010 تمامی نسخه های VB (شمال دانت نتی و VB6) برای ادامه کد تو خط بعدی نیاز داشتم که قبل از رفتن به خط بعد یک علامت فاصله و زیر خط ( _ ) گذاشته بشه یعنی خطی که به با _ تموم شده ادامه اش تو خط بعدی هست
از 2010 به بعد اومدن برای راحتی برنامه نویس در بعضی از نقاط قابل در که (مثلا پرانتز باز ، ویرگول و ...) الزام گذاشتن این زیر خط رو حذف کردن
من به شخصه این به جز در پاره موارد این حذف زیر خط رو نمی پسندم چون اغلب خوانایی کد های وی بی رو به شدت پایین میاره و خوندنش رو سخت می کنه (مثلا حتی برای منی که سالهاست با انواع وی بی کار می کنم)
برای همین من همیشه سعی می کنم زیر خط ها رو بذارم



دلیل این کد چیه توی کدهای بالا: :متفکر:
1
OnTextChanged(Nothing)




این کد متدی رو که زمان تغییر متن تکست باکس اجرا میشه رو صدا میزنه (بدون تغییر در مقدار فعلی) تا متن داخل تکست باکس اعتبار سنجی بشه و چون کد به پارامتر e نیاز نداره همون Nothing کفایت می کنه


ضمنا چرا میگید این کد دقیق تره؟ :متفکر:
اگه دقت کنید همه پراپرتی ها رو از حالت تک خطی (Implicit) خارج و به صورت کامل نوشتم و تو قسمت Set اقدام به اعتباری سنجی مجدد متن شده
دلیل:
فرض کنید در زمان اجرا حالت تکست باکس فقط عدد نباشه حالا در حین برنامه به دلایلی این خاصیتش فعال بشه تا فقط عدد وارد بشه
حالا اگه متن قبلی عدد نباشه ما تکست باکس داریم با حالت فقط عدد که داخلش مقدار غیر عددی داریم!
پس تو تغییر این پراپرتی ها اقدام به اعتبار سنجی صریح (اجباری) مقدار موجود می کنیم


اگه بخواهیم یک پروپرتی به صورت زیر مجموعه یک پروپرتی دیگه بنویسیم باید چیکار کنیم(اصلا اینجوری میشه؟)؟ (مثل فونت که زیر مجموعه داره؟)
این نوع پراپرتی ها از نوع ساده (Integer,String,...) نیستن یعنی خودشون یه کلاس هستن

جهت آزمایش یه یوزر کنترل به این صورت ایجاد و پروژه رو بیلد و یک نمونه داخل فرم بندازید
بعد به لیست پراپرتی ها نگاه و به MyBtn دقت کنید

Public Class UserControl1

Public Property MyBtn As Button
Private Sub UserControl1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
MyBtn = New Button
End Sub
End Class

mehdi_79
سه شنبه 19 دی 1391, 18:32 عصر
خاصیت حداکثر مقدار عددی کار نمی کند لطفا چک کنید

فرید نجفلو
سه شنبه 19 دی 1391, 19:09 عصر
خاصیت NomericOnly رو هم باید True کنید
چک کنید

mehdi_79
سه شنبه 19 دی 1391, 19:15 عصر
تا زمانی که SeparatNumber برابر FALSE است کار می کند وقتی TRUE شد کار نمی کند
با تغییرات جزیی مشکل انتخاب همزمان دو خاصیت NumericOnly و MaxNumValue و محدودیت MaxNumValue را حل کردم

Imports System.ComponentModel
Public Class NumericTextBox

Inherits TextBox

''' <summary>
''' آخرین مقداری که در تکست باکس به صورت مجاز وارد شده است
''' </summary>
''' <remarks></remarks>
Private LastText As String = ""

Private _NumericOnly As Boolean = False
<Description("ورودی فقط عددی"), DefaultValue(False), Category("FOR NUMBERS")> _
Public Property NumericOnly() As Boolean
Get
Return _NumericOnly
End Get
Set(ByVal value As Boolean)
_NumericOnly = value
OnTextChanged(Nothing)
End Set
End Property

Public _MaxNumValue As Decimal = 0
<Description("حد بالای مقدار وارد شده در حالت عددی. درصورتی که این مقدار برابر 0 باشد این پروپرتی غیرفعال خواهد بود"), DefaultValue(0), Category("FOR NUMBERS")> _
Public Property MaxNumValue() As Decimal
Get
Return _MaxNumValue
End Get
Set(ByVal value As Decimal)
_MaxNumValue = value
OnTextChanged(Nothing)
End Set
End Property


Public _SeparatNumber As Boolean = False
<Description("جدا کردن سه رقمی اعداد"), DefaultValue(False), Category("FOR NUMBERS")> _
Public Property SeparatNumber() As Boolean
Get
Return _SeparatNumber
End Get
Set(ByVal value As Boolean)
_SeparatNumber = value
OnTextChanged(Nothing)
End Set
End Property


Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
If Me.NumericOnly AndAlso Not (Char.IsDigit(e.KeyChar) OrElse Char.IsControl(e.KeyChar)) Then
e.KeyChar = Nothing
End If
MyBase.OnKeyPress(e)
End Sub

Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
MyBase.OnTextChanged(e)
If Me.Text <> "" AndAlso Me.NumericOnly AndAlso Not IsNumeric(Me.Text) Then
If IsNumeric(LastText) Then Me.Text = LastText Else Me.Text = ""
Me.Select(Me.Text.Length, 0)

End If

If NumericOnly AndAlso IsNumeric(Me.Text) AndAlso CDec(Me.Text) > MaxNumValue AndAlso MaxNumValue <> 0 Then
If IsNumeric(LastText) Then Me.Text = LastText Else Me.Text = ""
End If

If NumericOnly AndAlso SeparatNumber AndAlso IsNumeric(Me.Text) Then
Me.Text = FormatNumber(Me.Text, 0, TriState.False, TriState.UseDefault, TriState.UseDefault)
End If
Me.Select(Me.Text.Length, 0)

LastText = Me.Text
End Sub

End Class

ghayour
سه شنبه 19 دی 1391, 23:06 عصر
این به نظرم نوعی کلک زدن هست که به اعشاری تبدیل کنی!
این هم مشکلاتی داره مثل وقتی مقدار رقم زیاد می نویسی کل برنامه خطا میده. مقدار MaxNumValue رو صفر بذار و SeparatNumber رو true قرار بده حالا روی یکی از ارقام انگشتت رو نگه دار تا رقم زیادی توی تکست باکس بنویسه میبینی که برنامه خطا میده.

و مشکل دومی که هردوتا دارن اینه که وقتی SeparatNumber فعال هست وقتی به همین صورت عددی مینویسی و عدد زیادی میشه همه‌ی عدد رو به یکباره تغییر میده و به صفر تبدیل میکنه و بعد از اون هر عددی رو بنویسی به جاش صفر میگذاره.

(هر چند مشکل دوم به نظرم زیاد مهم نباشه ولی مشکل اولی مهمه)

mehdi_79
پنج شنبه 21 دی 1391, 22:23 عصر
کد اصلاح شده زیر تمامی مشکلات فوق را حل می کند توابع استاندارد Vb بعضا جوابگوی نیاز ها نیست لذا دو تابع مورد نیاز را خودم نوشتم


Imports System.ComponentModel
Public Class NumericTextBox

Inherits TextBox

''' <summary>
''' آخرین مقداری که در تکست باکس به صورت مجاز وارد شده است
''' </summary>
''' <remarks></remarks>
Private LastText As String = ""

Private _NumericOnly As Boolean = False
<Description("ورودی فقط عددی"), DefaultValue(False), Category("FOR NUMBERS")> _
Public Property NumericOnly() As Boolean
Get
Return _NumericOnly
End Get
Set(ByVal value As Boolean)
_NumericOnly = value
OnTextChanged(Nothing)
End Set
End Property

Public _MaxNumValue As ULong = 0
<Description("حد بالای مقدار وارد شده در حالت عددی. درصورتی که این مقدار برابر 0 باشد این پروپرتی غیرفعال خواهد بود"), DefaultValue(0), Category("FOR NUMBERS")> _
Public Property MaxNumValue() As ULong
Get
Return _MaxNumValue
End Get
Set(ByVal value As ULong)
_MaxNumValue = value
OnTextChanged(Nothing)
End Set
End Property

Public _SeparatNumber As Boolean = False
<Description("جدا کردن سه رقمی اعداد"), DefaultValue(False), Category("FOR NUMBERS")> _
Public Property SeparatNumber() As Boolean
Get
Return _SeparatNumber
End Get
Set(ByVal value As Boolean)
_SeparatNumber = value
OnTextChanged(Nothing)
End Set
End Property

Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
If Me.NumericOnly AndAlso Not (Char.IsDigit(e.KeyChar) OrElse Char.IsControl(e.KeyChar)) Then
e.KeyChar = Nothing
End If
MyBase.OnKeyPress(e)
End Sub

Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
MyBase.OnTextChanged(e)
If Me.Text <> "" AndAlso Me.NumericOnly AndAlso Not IsNumeric(Me.Text) Then
If IsNumeric(LastText) Then Me.Text = LastText Else Me.Text = ""
End If

If NumericOnly AndAlso IsNumeric(Me.Text) AndAlso Val(UNSeparatNumberi(Me.Text)) > MaxNumValue AndAlso MaxNumValue <> 0 Then
If IsNumeric(LastText) Then Me.Text = LastText Else Me.Text = ""
End If

If NumericOnly AndAlso SeparatNumber AndAlso IsNumeric(Me.Text) Then
Me.Text = SeparatNumberi(UNSeparatNumberi(Me.Text))
End If
Me.Select(Me.Text.Length, 0)

LastText = Me.Text
End Sub

Private Function UNSeparatNumberi(ByVal s As String) As String
UNSeparatNumberi = s.Replace(",", "")
End Function

Private Function SeparatNumberi(ByVal s As String) As String
Dim si As String = ""
Dim n As Integer = Len(s)

Dim Pi As Integer = n \ 3
Dim ni As Integer
ni = n Mod 3
If ni > 0 Then
si = Mid(s, 1, ni) & ","
End If
Dim i As Integer
For i = 0 To Pi - 1
si = si & Mid(s, ni + i * 3 + 1, 3) & ","
Next
SeparatNumberi = si.Remove(Len(si) - 1, 1)

End Function

End Class

ghayour
پنج شنبه 21 دی 1391, 22:37 عصر
این کد مشکل داره:
وقتی SeparatNumber فعال هست از 3 رقم بیشتر نمینویسه. :ناراحت:

mehdi_79
پنج شنبه 21 دی 1391, 22:55 عصر
باید SeparatNumber و NumericOnly همزمان TRUE باشد در ضمن MaxNumValue باید صفر یا مقدار دلخواه باید باشد
قبل از احرا rebuild کنید

ghayour
پنج شنبه 21 دی 1391, 23:12 عصر
متاسفانه مشکل سرجاش هست.
هم SeparatNumber و هم NumericOnly همزمان True هستند.
شما یک پروژه جدید باز کن و این کنترل رو از همین جا کپی کن، شاید نسبت به اونی که امتحان میکنی کمی فرق کنه!!

mehdi_79
پنج شنبه 21 دی 1391, 23:32 عصر
پروژه شامل کد فوق را ضمیمه کردم
VB من 2005 است که فکر نمی کنم فرقی کند

ghayour
پنج شنبه 21 دی 1391, 23:47 عصر
من از نسخه Visual Studio 2010 استفاده میکنم.
مثل اینکه نتونست به طور کامل به 2010 تبدیل کنه ولی همین کدهایی که نوشته بودید هم اونجا بود اما هنوز هم همین مشکل هست و وقتی SeparatNumber فعال هست از سه رقم بیشتر نمی‌نویسد.

mehdi_79
پنج شنبه 21 دی 1391, 23:53 عصر
در پوشه TEST_NUM_TEXT_BOX\TEST_NUM_TEXT_BOX\bin\Release پروژه فایل آماده پروژه به نام TEST_NUM_TEXT_BOX موجود است نتیجه را چک کنید
صحیح کار می کند اگر حل نشد برای 2010 هم بسازم

ghayour
جمعه 22 دی 1391, 00:00 صبح
حتی قبل از اینکه بازش کنم و به 2010 تبدیل بشه فایل exe داخل پوشه Release یا Debug هم همینطوری هست.

mehdi_79
جمعه 22 دی 1391, 00:30 صبح
دو باره برای 2010 ساختم و کاملا کار می کند سایر عزیران هم چک کنند و تنیجه را بگویند

ghayour
جمعه 22 دی 1391, 09:41 صبح
هیچ فرقی نسبت به قبل نکرد و هنوز هم کار نمی‌کند.