PDA

View Full Version : پرش از کنترلی به کنترل دیگر در فرم بوسیله enter



musiox
جمعه 28 اردیبهشت 1386, 16:27 عصر
یکی از کارهایی که برای سرعت دادن به عملیات پیمایش فرم در هنگام پر کردن آن می باشد , پرش از کنترلی به کنترل دیگر بوسیله وارد کردن کلید enter و بدون بردن موس و کلیک کردن بر روی کنترل مورد نظر است . فکر کنم همه برنامه نویسای vb.net از روش تعریف رویداد keyress و نوشتن کد مور نظرشان برای پرش برای تمامی کنترلهای فرمشون استفاده می کنن که هم خیلی وقت گیره و هم کد های برنامه رو زیاد می کنه . ولی به نظر می رسه که تنها راهه ممکن برای اینکاره
. ولی من یه راهه بسیار بهتر و راحتتر و کمتر رو پیدا کردم که فکر کنم همتون خوشتون بیاد و کلی منو برای اینکار دعا کنین . خوب اون راهه با حاله من درآوردی اینه :
اگه با ساختار ایونت یه کم آشنا باشین میدونین که دو تا پارامتر داره 1.sender که اطلاعاتی در مورد فراخواننده رویداد به گرداننده ارسال میکنه 2.e که یکسری آرگومانهای رویداد است .
اول یه آرایه از شماره های کنترل هامون ایجاد می کنیم .


Dim indexarray() As Integer = {3, 2, 1}

سپس در بخش لود فرم برای هر کدام از کنترل های فرم که در این آرایه آمده اند یک رویداد keypress تعریف می کنیم که باعث می شود در هنگام فشردن کلید ها در فرم ما و بر روی کنترل های مورد نظر , ساب mykeypress به عنوان گرداننده رویداد فراخوانی شود . همانطور که در رویداد لود فرم می بینید ما متغیر دیگری نیز داریم که از کلاس مجموعه است و اعضای آن متشکل از نام کنترل به عنوان کلید و شماره کنترل بعدی که می خواهیم به آن پرش کنیم به عنوان آیتم می باشند که در بدنه کلاس فرم ما تعریف می شود .


Dim carray As New Collection

این هم رویداد لود کلاس . البته به دستورات else درون این رویداد توجه کنید چون برای پرش به آخرین کنترل از آن استفاده می شود یعنی شماره آن کنترل به جای صفر می آید .



Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim i As Integer
For i = 0 To indexarray.Length - 1
AddHandler Me.Controls.Item(indexarray(i)).KeyPress, AddressOf mykeypress
If i <> indexarray.Length - 1 Then
carray.Add(indexarray(i + 1), Me.Controls.Item(indexarray(i)).Name)
Else
carray.Add(0, Me.Controls.Item(indexarray(i)).Name)
End If
Next
End Sub


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



Sub mykeypress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
If ChrW(System.Windows.Forms.Keys.Enter) = e.KeyChar Then
Dim a As System.Reflection.PropertyInfo
Dim f As Object
a = sender.GetType.GetProperty("Name")
Dim j() As Object = {}
Me.Controls.Item(carray.Item(a.GetValue(sender, j).ToString)).Focus()
End If
End Sub


این برنامه توی vb.net 2003 درست شده .

sh
جمعه 28 اردیبهشت 1386, 19:49 عصر
به جای اینهمه کد نویسی و توضیح کافیه کارهای زیر رو انجام بدی :

در Form پروپرتی keyPreview رو برابر True قرار بده و بعد از Sort کردن TabIndex کنترلها بوسیله منوی view و گزینه Tab Order در رویداد KeyPress فرم مورد نظر بنویس :



If e.KeyChar = Convert.ToChar(13) Then
e.Handled = True
SendKeys.Send("{Tab}")
End If

PC2st
جمعه 28 اردیبهشت 1386, 22:00 عصر
دقیقا کدهای شما رو متوجه نشدم، ولی فکر کنم تقریبا مثل همین کد زیر ( یا بهتر از این ) باشه.
تعریف کلاس :


Public Class ControlPassing
Public Shared Sub KeyPressNextControl(ByRef ctrl As Control)
AddHandler ctrl.KeyPress, AddressOf OnKeyPress
End Sub
Private Shared Sub OnKeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs)
If e.KeyChar = ChrW(13) Then
Dim ctrl As Control = CType(sender, Control)
ctrl.FindForm().SelectNextControl(ctrl, True, True, False, True)
End If
End Sub
End Class

برای استفاده از اون هم کافیه که اشیائی که میخوایم با enter به کنترل بعدی بره رو واسش مشخص کنیم :


ControlPassing.KeyPressNextControl(Me.TextBox1)
ControlPassing.KeyPressNextControl(Me.TextBox2)
ControlPassing.KeyPressNextControl(Me.TextBox3)
ControlPassing.KeyPressNextControl(Me.TextBox4)

فقط اشیاء باید در فرم قرار گرفته باشند.

sh
شنبه 29 اردیبهشت 1386, 15:42 عصر
کدی که من نوشتم سریعترین و راحترین راه ممکن هست .
شما فکر کن 50 تا TextBox داری باید چقدر کد بنویسی ولی روشی که من گفتم فقط همون چند خطی هست که میبینی حالا اگر فرم 100 تا آبجکت هم داشته باشه فرقی نمیکنه

maroot
شنبه 29 اردیبهشت 1386, 23:13 عصر
با روش آقای sh موافقم , یه راهه دیگه اینه که یک Button به صورت hiden shoji و آن را Accept Button فرممون قرار بدیم و در رویدان Click این Button این کد رو بنویسیم:


sendkeys.send("{tab}")


اما یک سوال:
اگه بخوام وقتی که focus بر روی یک Button هست، کلید Tab کاری به جز انتقال focus رو انجام بده، باید چکار کنیم؟

musiox
دوشنبه 31 اردیبهشت 1386, 18:11 عصر
من هم با نظر آقای sh موافقم . کوتاهترین, بهترین و خلاقانه ترین روش .

Microsoft.net
سه شنبه 01 خرداد 1386, 15:18 عصر
به جای اینهمه کد نویسی و توضیح کافیه کارهای زیر رو انجام بدی :

در Form پروپرتی keyPreview رو برابر True قرار بده و بعد از Sort کردن TabIndex کنترلها بوسیله منوی view و گزینه Tab Order در رویداد KeyPress فرم مورد نظر بنویس :



If e.KeyChar = Convert.ToChar(13) Then
e.Handled = True
SendKeys.Send("{Tab}")
End If


روش ساده و سریعی هست فقط یه اشکال بزرگ داره !! و اونم اینکه موقع trace کردن برنامه اگه به خط sendkey.send برسی صفحه کلید قفل میکنه ، دلیلشم فکر میکنم ناسازگاری دستور با محیط دات نت باشه چون این دستور معروفی در vb6 بوده و احتمالا معادلی تو دات نت نتونستن براش پیدا کنن . به هر حال اگه امتحان کنین متوجه میشین که باگ داره

musiox
سه شنبه 01 خرداد 1386, 16:52 عصر
من امتحانش کردم مشکلی نبود . تو دات نت برای خودش کلاس داره .
System.Windows.Forms.SendKeys

حامد مصافی
سه شنبه 01 خرداد 1386, 17:01 عصر
خود دات نت متدی به نام SelectNextControl برای شی فرم تدارک دیده. این متد امکان انتخاب کنترل بعدی در شرایط انتخابی مانند انتخاب در یک سطح یا انتخاب کنترل های قابل رهگیری تمرکز است
یک نمونه از استفاده :


Private Sub fMain_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.Up
Me.SelectNextControl(Me.ActiveControl, False, True, False, True)

Case Keys.Down
Me.SelectNextControl(Me.ActiveControl, True, True, False, True)

End Select

End Sub

Microsoft.net
سه شنبه 01 خرداد 1386, 19:13 عصر
من امتحانش کردم مشکلی نبود . تو دات نت برای خودش کلاس داره .
System.Windows.Forms.SendKeys

چی رو امتحان کردی ؟! عرض کردم موقع trace کردن برنامه (خط به خط) و رسیدن به کد مذکور صفحه کلید قفل میکنه وگرنه توی runtime که مشخصه مشکلی نداره

musiox
سه شنبه 01 خرداد 1386, 21:33 عصر
SendWait چی ؟
درضمن وقت تریس بعد از یک بار قفل کردن و زدن Ctrl + Alt + Del و برگشتن به حالت عادی , توی تکرارهای بعدی دیگه قفل نمی کنه . چرا؟
-- در ضمن کامپیوتر من دوخط در میون تریس می کنه دفه قبل این خط رو ندید .--

saeed_rezaei
سه شنبه 01 خرداد 1386, 23:31 عصر
پس با جمع بندی کدهای دوستان عزیز آقایان sh و blackdal به این کد می رسیم.
به همون روشی که اقای sh گفتد شروع می کنیم کد ترکیبی ایشان را با کد آقایblackdal در تابع keypress می نویسیم.



PrivateSub Form1_KeyPress(ByVal sender AsObject, ByVal e As System.Windows.Forms.KeyPressEventArgs) HandlesMe.KeyPress
Dim c AsNew Control
c = Me.GetNextControl(Me.ActiveControl, True)
If e.KeyChar = Convert.ToChar(13) Then
e.Handled = True
If c IsNotNothingThen c.Focus()
EndIf
EndSub

rezaei manesh
چهارشنبه 02 خرداد 1386, 09:24 صبح
سلام
من تا الان از روش آقا شهریار استفاده می کردم و هیچ مشکلی هم نبود اما با دیدن روش جناب مصافی تصمیم دارم روش رو به کد ایشان تغییر بدم چون امکانات دیگه هم داره که بسیار ساده در اختیار ما قرار می ده مثل برگشت به عقب و کد نویسی کمتری هم داره باید امتهان کنم ببینم چطور جواب می ده

sh
چهارشنبه 02 خرداد 1386, 15:33 عصر
برگشت به عقب با زدن کلید Shift + tab انجام میشه و در ضمن با سورت tabIndex شما به راحتی میتونین مشخص کنین کنترل بعدی کدوم خواهد بود

rezaei manesh
چهارشنبه 02 خرداد 1386, 15:45 عصر
خوب شیفت تپ رو می دونم اگه اون طوری حساب کنیم با تپ هم می تونیم بریم بعدی
سورت رو هم که معلومه خوب
منظور من این بود که همان طور که برای راحتی کار علاوه بر دکمه tab ما دکمه enter رو هم به کمکش میاریم می تونیم به جای shiftTab دکمه دیگری مثلا Up رو در اختیار کاربر بزاریم
من خودم همون طور که گفتم تا حالا از روشی که شما استفاده می کنید استفاده می کردم
اما الان می خوام از روس آقای مصافی استفاده کنم(شاید یکی از دلایل هم این باشه که این روش دات نتی تر هستش البته شاید گفتم می دونم که sendtab هم در دات نت کلاس داره و...)
نظر شما درباره روش آقای مصافی چیه؟

musiox
چهارشنبه 02 خرداد 1386, 21:48 عصر
باید توجه داشته باشیم که اگه در حالتی که از کنترل ها و متد های آنها استفاده می کنیم باید در فرم ترتیب قرار دادنشان رعایت شود و اگر بعدا یک کنترل جدید به آن اضافه کنیم [ فکر کنم ] به مشکل بر بخوریم .
یه نکته دیگه هم اینکه اگه از RadioButton در فرم استفاده می کنیم برای استفاده از کد آقای sh باید یکی از این RadioButton ها انتخاب شده باشد در غیر اینصورت از مجموعه آنها پرش می کنیم .
کدهای blackdal و saeed_rezaei هم خوبه ولی وقتی کنترل فعال تغییر می کنه در کنترل های RadioButton و CheckBox به سختی این موضوع مشخص می شود که آیا کنترل فعال است یا خیر . در کد آقای saeed_rezaei مسئله بازگشت به کنترل قبلی باید در نظر گرفته شود . یعنی از یک select case استفاده شود و اگر دکمه up زده شده بود مقدار آرگومان دوم GetNextControl برابر با False باشه و اگه Enter بقیه ماجرا .
در کد آقای sh هم برای بازگشت به کنترل قبلی همینطور که خودشان گفتن از
SendKeys.Send("+{TAB}")
استفاده می کنیم و باید به جای استفاده از رویداد KeyPress از KeyDown استفاده کنیم .
به هر حال به شخصه من کد آقای sh رو برای کار انتخاب میکنم البته با SendWait .
حالا من به یه مسئله دیگه برخورد کردم اونم تایید صحت ورودی کاربر در هنگام پرش است . این درسته که ما در هنگام تایید مطالب وارد شده توسط کاربر آنها را چک می کنیم ولی شاید بهتر باشه که در هنگام پرش ها هم چک صورت بگیره تا اگه کاربر مشکلی در ورود داده ها داره از پرش جلوگیری بشه و پیغام مناسب به کاربر نشان داده شود .
در ضمن Microsoft.net ، متد send در clr debugger باعث قفل شدن نمی شه .

maroot
چهارشنبه 02 خرداد 1386, 23:45 عصر
در این موقع باید در روال Leave کنترلمون اگر داده درست وارد نشده بود به همین کنترل Focus کنه و معمولا من اینجا از ErrorProvider هم استفاده می کنم

linux
پنج شنبه 03 خرداد 1386, 11:48 صبح
وقتی برای ویندوز برنامه می نویسید حداقل یکسری استاندارد ها را رعایت کنید.در برنامه های تحت داس و بیشتر فاکس پرو بود که با زدن کلید enter می رفتید به فیلد بعدی در ویندوز این کار با TAB هست برای مثال برنامه address book خود ویندوز را ببنید یک برنامه نمونه برای کار با دیتا و کنترل ها هست.
وظیفه کلید enter یک چیز جدا هست به معنی تایید و ثبت اطلاعات اگر تو برنامه هاتون این چند مورد را رعایت کنید احتیاج به اینقدر جدل نیست.
اگر هم کاربران شما اصرار به این دارند مهم نیست بعد از مدتی عادت می کنند.
یاد می گیرند که با دو دست کار کنند.

Microsoft.net
پنج شنبه 03 خرداد 1386, 12:10 عصر
وقتی برای ویندوز برنامه می نویسید حداقل یکسری استاندارد ها را رعایت کنید.در برنامه های تحت داس و بیشتر فاکس پرو بود که با زدن کلید enter می رفتید به فیلد بعدی در ویندوز این کار با TAB هست برای مثال برنامه address book خود ویندوز را ببنید یک برنامه نمونه برای کار با دیتا و کنترل ها هست.
وظیفه کلید enter یک چیز جدا هست به معنی تایید و ثبت اطلاعات اگر تو برنامه هاتون این چند مورد را رعایت کنید احتیاج به اینقدر جدل نیست.
اگر هم کاربران شما اصرار به این دارند مهم نیست بعد از مدتی عادت می کنند.
یاد می گیرند که با دو دست کار کنند.

آمریکایی ها tab کارند ولی شرقی ها مخصوصا خاور میانه ای ها enter کارند ، واسه همین سخته براشون ...

linux
پنج شنبه 03 خرداد 1386, 12:16 عصر
آمریکایی ها tab کارند ولی شرقی ها مخصوصا خاور میانه ای ها enter کارند ، واسه همین سخته براشون ...
یعنی چی این حرف؟!
این را از کجا نتیجه گرفتی مگر فاکس پرو و برنامه های داس فقط توی شرق بوده؟!
توجیه هم می کنید یک چیز بگید بگنجه

Alireza_Salehi
پنج شنبه 03 خرداد 1386, 13:02 عصر
وقتی برای ویندوز برنامه می نویسید حداقل یکسری استاندارد ها را رعایت کنید.در برنامه های تحت داس و بیشتر فاکس پرو بود که با زدن کلید enter می رفتید به فیلد بعدی در ویندوز این کار با TAB هست برای مثال برنامه address book خود ویندوز را ببنید یک برنامه نمونه برای کار با دیتا و کنترل ها هست.
وظیفه کلید enter یک چیز جدا هست به معنی تایید و ثبت اطلاعات اگر تو برنامه هاتون این چند مورد را رعایت کنید احتیاج به اینقدر جدل نیست.
اگر هم کاربران شما اصرار به این دارند مهم نیست بعد از مدتی عادت می کنند.
یاد می گیرند که با دو دست کار کنند.

بعضی جاها که سرعت کار زیاده مثل بانک ها این کار سرعت رو زیاد میکنه چون کاربر صرفا با استفاده از قسمت ماشین حساب صفحه کلید تمام عملیات رو انجام میده، تقریبا اکثر نرم افزار های بانکی که من دیدم این طوری بودند!

Microsoft.net
پنج شنبه 03 خرداد 1386, 13:19 عصر
یعنی چی این حرف؟!
این را از کجا نتیجه گرفتی مگر فاکس پرو و برنامه های داس فقط توی شرق بوده؟!
توجیه هم می کنید یک چیز بگید بگنجه

به طور مثال Microsoft Money که معروف ترین نرم افزار Accounting غربی هست به هیچ عنوان و در هیچ جا از enter برای رفتن به کنترل بعدی استفاده نمیکنه ولی مثلا سیستم جامع اتوماسیون همکاران سیستم و یا رایورز که نسخه های زیادی توی دبی و امارات فروختن و تو ایران هم معروف هستند همه جا از enter استفاده کردند و مورد توجه کاربران هم قرار گرفته

بنده اینو از یکی از اساتید حسابداری شنیدم که نوع چیدمان اسناد مالی و رسمی غربی ها مخصوصا انگلیس و آمریکا جوریه که کاربران اونها عادت کردن با Tab کار کنند و راحت ترند ولی برای کشور های Right to Left مثل ایران و کشور های عربی این بر عکس هست
حالا گنجید ؟!!

linux
پنج شنبه 03 خرداد 1386, 20:19 عصر
به طور مثال Microsoft Money که معروف ترین نرم افزار Accounting غربی هست به هیچ عنوان و در هیچ جا از enter برای رفتن به کنترل بعدی استفاده نمیکنه ولی مثلا سیستم جامع اتوماسیون همکاران سیستم و یا رایورز که نسخه های زیادی توی دبی و امارات فروختن و تو ایران هم معروف هستند همه جا از enter استفاده کردند و مورد توجه کاربران هم قرار گرفته

بنده اینو از یکی از اساتید حسابداری شنیدم که نوع چیدمان اسناد مالی و رسمی غربی ها مخصوصا انگلیس و آمریکا جوریه که کاربران اونها عادت کردن با Tab کار کنند و راحت ترند ولی برای کشور های Right to Left مثل ایران و کشور های عربی این بر عکس هست
حالا گنجید ؟!!
رایورز و همکارن سیستم برنامه هاشون تخت داس بود همونها را تبدیل کردند به ویندوز با همون استاندارهای داس.
سند حسابداری و عدد زدن دیگر چپ و راست نداره که

musiox
پنج شنبه 03 خرداد 1386, 20:32 عصر
باید قبول کنیم که سرعته کار رو زیاد می کنه و کار کاربر رو راحت تر . چون من چند نمونه دیدم که از بابت اینکه از موس کمتر استفاده می کنن رضایت بیشتری داشتن تا اینکه از موس استفاده کنن .

maroot
جمعه 04 خرداد 1386, 01:54 صبح
طبعا هیچ برنامه نویسی هم نمی خواد کار خودشو سخت کنه و یا با زیر پا گذاشتن استانداردها برنامه خودشو زیر سوال ببره، ولی وقتی به یه کارفرما فوق العاده سمج که هیچ دلیل و بهانه ای و صغری کبری ای حالیش نمیشه بر بخوری دیگه مجبوری.

musiox
جمعه 04 خرداد 1386, 09:12 صبح
سیستم حسابداری آسمان رو یه نگاه بندازید بد نیست .

sinpin
سه شنبه 29 آبان 1386, 12:07 عصر
کدی که من نوشتم سریعترین و راحترین راه ممکن هست .
شما فکر کن 50 تا TextBox داری باید چقدر کد بنویسی ولی روشی که من گفتم فقط همون چند خطی هست که میبینی حالا اگر فرم 100 تا آبجکت هم داشته باشه فرقی نمیکنه

موافق نیستم - چون شما میتونید یک derived control بسازید که این عمل رو بصورت built-in و اتوماتیک (فقط با true کردن یک خاصیت) براتون انجام بده.
در این حالت دیگه هیچوقت مجبور به تکرار اون چندخط کد هم نخواهید بود.

rezaei manesh
چهارشنبه 30 آبان 1386, 13:18 عصر
خوب این هم روشی هست که به ظاهر خوب به نظر می رسه حالا شما پس لطف کن و در مورد derived control و کاری که می گی بیشتر توضیح بده و نمونه بزار

sinpin
جمعه 02 آذر 1386, 09:44 صبح
خوب این هم روشی هست که به ظاهر خوب به نظر می رسه حالا شما پس لطف کن و در مورد derived control و کاری که می گی بیشتر توضیح بده و نمونه بزار

سلام
من یه مثال خیلی ساده ارسال کردم. در این حالت شما یک boolean property دارید که میتونید بگید کدوم کنترل ها این خاصیت رو داشته باشند.

مهدی نان شکری
جمعه 02 آذر 1386, 11:59 صبح
با سلام
من هم تا زمانی که Office Accounting رو ندیده بودم ، فکر می کردم enter نباید کار tab رو هم انجام بده. ولی نرم افزار بالا هم گویا این کار رو کرده.