PDA

View Full Version : maskedTextBox



mina1363
یک شنبه 28 مرداد 1386, 13:06 عصر
سلام
من یک textbox دارم میخوام نحوۀ پر کردن کاربر در آن را محدود کنم و بگم که حتما باید به فرمتی مثل یک بیت شعری که دارای دو مصرع و space بین آنها وارد کنه چطوری میتونم این کار رو انجام بدم ؟

PC2st
یک شنبه 28 مرداد 1386, 13:46 عصر
برای اینکه کاربر حتما باید یک فاصله رو بین دو مصرع وارد کنه، اون فاصله میتونه مربوط به فاصله بین کلمات یا فاصله بین دو مصرع باشه! و در اینصورت، برنامه نمیتونه تشخیص بده که فاصله ای که کاربر وارد کرده، مربوط به فواصل بین کلمات است یا مربوط به فاصله بین دو مصرع؟

اما میشه کاری کرد که هر وقت کاربر 5 بار کلید Space رو فشار داد یا اینکه کلید Enter رو زد، اونوقت میخواد مصرع بعد رو بنویسه نه کلمه بعدی...

در صورتی که از MaskedTextBox استفاده نکنیم، با فرض اینکه کاربر بیت شعر رو در textBox1 وارد کنه و خاصیت RightToLeft از کنترل textBox1 روی true تنظیم شده باشه، در صورتی که بخوایم کار بالا رو انجام بدیم، کد زیر رو برای textBox1 مینویسیم:


private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
if (textBox1.Text.Contains(" "))
{
this.GetNextControl(textBox1, true).Focus();

return;
}

textBox1.Text += " ";
textBox1.SelectionStart = textBox1.Text.Length;

e.Handled = true;
}
}

در اینصورت اگر کلید Enter رو برای بار اول فشار بده (یا 5 بار فاصله ایجاد کنه)، یعنی شروع کرده که مصرع بعد رو بنویسه و اگر برای بار دوم کلید Enter رو بزنه، یعنی اینکه کل بیت وارد شده و فوکوس به کنترل بعد منتقل میشه. البته به جای 5 تا فاصله میشد از خط تیره "-" هم استفاده کرد.
برای مشخص کردن اینکه کاربر میخواد مصرع دوم رو وارد کنه، میتونستیم یک متغیر از نوع bool هم تعریف کنیم.
برای پیاده سازی این کار، میشداز روشهای دیگر هم استفاده کرد مثلا بعد از ورود کاربر، توسط عبارات باقاعده، چک کنیم که ایا بیت شعر وارد شده یا نه...
برای MaskedTextBox چون فکر کنم طول داده هائی که وارد میشه باید ثابت باشه، پس نمیشه از این کار برای آن استفاده کرد.

mina1363
یک شنبه 28 مرداد 1386, 16:49 عصر
حالا میخوام همین داخل یک شرط باشه یعنی وقتی کاربر به صورت یک بیت تایپ نکرد بهش پیغام خطا بده چون اینو میخواستم نتونستم اجرای کد بالا رو درست ببینم

PC2st
یک شنبه 28 مرداد 1386, 17:39 عصر
در رویداد Validating میشه کدهای زیر رو نوشت:


private void textBox1_Validating(object sender, CancelEventArgs e)
{
int index = textBox1.Text.IndexOf(" --- ");
if (index == -1)
{
MessageBox.Show("لطفا یک بیت شعر بنویسید");
e.Cancel = true;
}
else if (textBox1.Text.Substring(index + 5).Trim() == "")
{
MessageBox.Show("لطفا مصراع دوم را بنویسید");
e.Cancel = true;
}
}


بهتره که رویدادهای Validating و KeyPress از textBox1 رو در حین ارث بری از کلاس TextBox انجام بدیم، تا دیگه این کدها (کدهای بالا و کدهای قبلی) در کدهای فرم دیده نشند، اینطوری برنامه رو راحت تر میشه توسعه داد. مثلا کلاس زیر ور در داخل فضای نام برنامه (مثلا WindowsApplication1) و در کنار کلاس فرم (مثلا Form1) قرار بدید:


class MyCustomTextBox : TextBox
{
private const string separator = " ::: ";
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
if (this.Text.Contains(separator))
{
this.FindForm().GetNextControl(this, true).Focus();
return;
}
this.Text += separator;
this.SelectionStart = this.Text.Length;
e.Handled = true;
}
base.OnKeyPress(e);
}
protected override void OnValidating(CancelEventArgs e)
{
int index = this.Text.IndexOf(separator);
if (index == -1)
{
MessageBox.Show(".لطفا یک بیت شعر بنویسید");
e.Cancel = true;
}
else if (this.Text.Substring(index + 5).Trim() == "")
{
MessageBox.Show(".مصراع دوم را فراموش کردید");
e.Cancel = true;
}
base.OnValidating(e);
}
}

اگر از کلاس بالا یک شیئ ایجاد کنید و آن شیئ رو به فرمتون اضافه کنید، اینطوری دیگه textBox ای که برای گرفتن بیت بکار میره، کدهای مربوط به رویداد KeyPress و Validating اش در فرم نیست و کدهای برنامه راحت تر سازماندهی میشه.
اگر میخواید کلاس بالا به قسمت Toolbox اضافه بشه، یکبار برنامه رو با F5 اجرا کنید، آنوقت میتوانید یک کنترل از نوع MyCustomTextBox را از Toolbox روی فرم بکشید.

mina1363
یک شنبه 28 مرداد 1386, 20:29 عصر
مرسی واقعا لطف کردید همونی بود که میخواستم فقط جسارتا میشه خواهش کنم یه توضیحی راجع به validating بدید من نفهمیدم چرا باید شرط را داخل اون مینوشتم؟
getNextControl چیکار میکنه ؟
باز هم مرسی
شما میتونید سؤال اتصال به تلفن را هم بدهید یکی از دوستان گفت باید dll اش را بخرم ولی من میخوام خودم هم یاد بگیرم PLZZZZZZ

mina1363
یک شنبه 28 مرداد 1386, 20:40 عصر
حالا می خوام یک چیزی مثل کرنومتر بذارم که مدت زمانی که کاربر داره تایپ میکنه را بگه برای این چیکار کنم ؟

mina1363
یک شنبه 28 مرداد 1386, 20:41 عصر
سلام
مرسی

mina1363
یک شنبه 28 مرداد 1386, 20:43 عصر
شما برای سؤال جدول کلمات متقاطع چه ایده ای دارید؟

PC2st
یک شنبه 28 مرداد 1386, 21:13 عصر
خواهش میکنم، باید از همون اول توضیح لازم رو میدادم و خوشحالم که این سوال رو پرسیدید.
رویداد Validating زمانی رخ میده که کاربر داده های خودش رو وارد کرده و دیگه کاری با کنترل (مثلا TextBox) نداره و میخواد به کنترل دیگه ای برود (مثلا یک TextBox دیگه)، در این حالت قبل از اینکه کاربر بتواند به کنترل دیگه ای برود، رویداد Validating رخ میده، قاعده این است که در این رویداد مورد بررسی قرار میدیم که آیا داده هائی که کاربر وارد کرده، صحیح است یا اینکه آن داده ها قابل قبول نیست؟ (به این قسمت Validate کردن میگیم) و اگر داده هائی که کاربر وارد کرده بود، قابل قبول نبود، اجازه خروج از کنترل (مثلا TextBox) رو به کاربر نمیدیم تا وقتی که داده ها رو درست وارد کنه.
رویداد Validated هم زمانی رخ میده که داده های وارد شده توسط کاربر، معتبر بوده است.

هر کنترل (مثلا TextBox) دارای یک متد بنام FindForm است، این متد به فرمی اشاره میکنه که کنترل در اون قرار داره، اما اگر کنترل در یک فرم قرار نداشت، دیگه این متد به هیچی اشاره نمیکنه و مقدار null رو برمیگردونه...
در کدهای چند پست قبل، توسط متد FindForm، شیئ فرمی که TextBox در اون قرار داره رو بدست آوردیم، سپس متد GetNextControl از این شیئ رو صدا زدیم.
همانطور که میدانید، یک فرم میتونه شامل چندین کنترل در داخل خودش باشه، مثلا یکی از این کنترلها همین TextBox ای بود که برای وارد کردن بیت از آن استفاده میشد، ممکن بود یک Button ای هم در این فرم بگذاریم که بیت رو در یک جدول ذخیره کنه و چندین کنترل دیگه...
توسط متد GetNextControl، میخواهیم ببینیم که بعد از یک کنترل، چه کنترلی وجود دارد؟
کد زیر رو همین جا میگذارم که دم دست باشه:


this.FindForm().GetNextControl(this, true).Focus();

this که به شیئ MyCustomTextBox اشاره میکنه (شیئی که از TextBox به ارث رسیده)، پس شیئ this یک کنترل است. متد FindForm از این شیئ رو صدا زدیم تا به Form ای که کتنرل در آن قرار دارد، دسترسی داشته باشیم، حال به فرم (Form) دسترسی داریم، متد GetNextControl را روی فرم اعمال میکنیم که این متد دو پارامتر میگیره، اولین پارامتر مشخص میکنه که ما میخوایم کنترل بعد از چه کنترلی رو دریافت کنیم؟ و پارامتر دوم مشخص میکنه که آیا بر اساس ترتیب فشرده شدن کلید Tab عمل بشه یا بر عکس آن.
که به متد GetNextControl شیئ this رو بعنوان اولین پارامتر ارسال کردیم تا به کنترل بعد از کنترل this، دسترسی داشته باشیم، سپس متد Focus را روی کنترل بعد از this، اعمال می کنیم تا آن کنترل برای کاربر فعال گردد. به این طریق کاربر به کنترل بعد، فرستاده میشود.




حالا می خوام یک چیزی مثل کرنومتر بذارم که مدت زمانی که کاربر داره تایپ میکنه را بگه برای این چیکار کنم ؟
میتوانید از کلاس Stopwatch یا TimeSpan استفاده کنید.




شما برای سؤال جدول کلمات متقاطع چه ایده ای دارید؟

شما میتونید سؤال اتصال به تلفن را هم بدهید یکی از دوستان گفت باید dll اش را بخرم ولی من میخوام خودم هم یاد بگیرم PLZZZZZZ
من اون پست ها رو دیدم، لطفا این سوالات رو در پست های دیگر، تکرار نکنید.

mina1363
دوشنبه 29 مرداد 1386, 04:59 صبح
مرسی ولی من یه تکه کد از stopwatch دیدم ولی اجرا نشد یعنی در خروجی چیزی نشان نداد
Stopwatch mywatch = newStopwatch();
if (button3.Text == "Start")
{

mywatch.Start();
button3.Text = "Stop";
sp.Play();


}
elseif (button3.Text == "Stop") {
mywatch.Stop();
sp.Stop();
button3.Text = "Start";
double TimeSpent = mywatch.ElapsedMilliseconds / 100;
label2.Text = string.Format("Elapsed time :{0} Seconds", TimeSpent.ToString("#,##.##"));

}

یا من اشتباه نوشتم یا . .. در کل اگه میشه اصلاحش کنید ممنون میشم

mina1363
دوشنبه 29 مرداد 1386, 05:00 صبح
چشم دیگه در پست های دیگه تکرارشون نمیکنم معذرت میخوام

PC2st
دوشنبه 29 مرداد 1386, 07:56 صبح
متغیر mywatch رو بصورت یک فیلد در کلاس تعریف کنید. مثلا برای button3 که متنش Start باشه، با کلیک روی اون زمان سپری شده رو حساب میکنه:


Stopwatch mywatch = new Stopwatch();

private void button3_Click(object sender, EventArgs e)
{
if (button3.Text == "Start")
{
mywatch.Start();
button3.Text = "Stop";
sp.Play();
}
else if (button3.Text == "Stop")
{
mywatch.Stop();
sp.Stop();
button3.Text = "Start";
double TimeSpent = mywatch.ElapsedMilliseconds / 100;
label2.Text = string.Format("Elapsed time :{0} Seconds", TimeSpent.ToString("#,##.##"));
}
}

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

mina1363
دوشنبه 29 مرداد 1386, 20:38 عصر
من وقتی از این اجرا میگیرم تو label هیچ زمانی را نشان نمیده

PC2st
دوشنبه 29 مرداد 1386, 21:51 عصر
آهان، ببخشید درسته :بامزه:
الان کدها رو دوباره مرور کردم، یک کار دیگه باید انجام بشه، خط زیر رو:


double TimeSpent = mywatch.ElapsedMilliseconds / 100;

به خط زیر تغییر بدید:


double TimeSpent = mywatch.ElapsedMilliseconds / 100D;

یعنی بعد از عدد 100 یک حرف D اضافه کنید، با اینکار وقتی عمل تقسیم صورت میگیره، طرفین عملگر "/" به نوع double تبدیل میشن که در اینصورت، نتیجه حاصل از تقسیم یک عدد اعشاری خواهد بود نه عدد صفر.

mina1363
سه شنبه 30 مرداد 1386, 14:53 عصر
مرسی PC2st.ir :-)