PDA

View Full Version : سوال: دسترسی به کنترل با استفاده از location



mh3242
یک شنبه 22 تیر 1393, 23:33 عصر
سلام دوستان
برای یه برنامه ای نیاز دارم وقتی رویداد mouse up یه کنترلی اتفاق می افته بفهمم که رو چه کنترلی این اتفاق می افته.
برای درک بهتر:
مثلا در فرم یه لیبل دارم و چند تا text box. کاربر لیبل رو روی یکی از تکست باکس ها میکشه. چطور میتونم متوجه بشم که رو کدوم یکیشون mouse up رو انجام میده.
اگه کمکی میکنه فرض رو بر این بزارید که کنترل ها با کد ایجاد شدن نه با درگ اند دراپ از tool box روی فرم.
به طور کلی میخوام بدونم وقتی mouse up انجام میشه mouse pointer اصلا داخل محدوده فرم هستش یا نه؟ (چون فرم تو اسکرین یه جای ثابت نیست و کاربر میتونه جاشو تغییر بده) و اگه داخل فرم هستش رو چه کنترلی رویداد مورد نظر رخ داده و چجوری به کنترل مورد نظر اشاره کنم؟
خیلی ممنون از کمک و راهنماییتون.

plus
یک شنبه 22 تیر 1393, 23:49 عصر
وقتی یک رویداد اتفاق میافته، شی ایجاد کننده رویداد توسط پارامتر sender به Handler ارسال میشه:

void textBox_MouseUp(object sender, MouseEventArgs e) {
TextBox textBox = sender as TextBox;
if (textBox != null) {
MessageBox.Show("MouseUp event on: " + textBox.Name);
}
}

اگه شما دارین از رویدادهای Drag&Drop استفاده میکنین با همین روش میتونید (با رویداد مربوطه) میتونید به کنترل ایجاد کننده رویداد دسترسی داشته باشین.

mh3242
یک شنبه 22 تیر 1393, 23:57 عصر
دسستت درد نکنه اما سوال رو دوباره بخون.
من به شی ایجاد کننده رویداد دسترسی کامل دارم. میخوام اون شی احتمالی که رویداد روش تمام میشه دسترسی داشته باشم.
نه از Drag&Drop استفاده نمیکنم. از mouse down و mouse move و mouse up استفاده میکنم.

plus
دوشنبه 23 تیر 1393, 00:55 صبح
با فرض اینکه کنترل ها مستقیما روی فرم (و نه روی GroupBox، Panel و ...) هستن،

private void label1_MouseUp(object sender, MouseEventArgs e) {
Point point = this.PointToClient(label1.PointToScreen(e.Location ));
Control control = this.GetChildAtPoint(point);
if (control != null) {
// ...
}
}

هرچند اگه واقعا عمل Drag Drop رو میخواین داشته باشین خیلی ساده تر و بهتر هست که از رویدادهای مربوط به DragDrop استفاده کنید.

mh3242
دوشنبه 23 تیر 1393, 12:08 عصر
خیلی ممنون از وقتی که گذاشتین و زحمتی که کشیدین.
کدی که دادین:
نمیتونم متوجه بشم به چی داره اشاره میکنه. با gettype نوعشو متوجه میشم، همونی هستش که باید باشه اما وقتی میخوام اسمشو ببینم رشته خالی بر میگردونه.
نمونه کد زیر هم:
textbox.text=control.text
هیچ کاری صورت نمیده.
این که می فرمائین drag&drop کنم در واقع کاری که من میخوام بکنم drag&swap location هستش. برا اینه که از رویدادهای drag&drop استفاده نکردم.
اگه بازم فکر میکنید drag&drop بهتره خیلی ممنون میشم یه توضیحی بفرمائین.

plus
دوشنبه 23 تیر 1393, 14:22 عصر
اول Control رو به Cast TextBox کنید تا حداقل از نوعش مطمین بشین.یا میتونید برای تست مثلا BackColor ش رو عوض کنید تا ببینید آیا اونی که میخواین هست یا نه!

if (control != null) {
control.BackColor = SystemColors.ActiveCaption;
TextBox textBox = control as TextBox;
if (textBox != nll) {
// ...
}
}

khokhan
دوشنبه 23 تیر 1393, 15:53 عصر
خیلی ممنون از وقتی که گذاشتین و زحمتی که کشیدین.
کدی که دادین:
نمیتونم متوجه بشم به چی داره اشاره میکنه. با gettype نوعشو متوجه میشم، همونی هستش که باید باشه اما وقتی میخوام اسمشو ببینم رشته خالی بر میگردونه.
نمونه کد زیر هم:
textbox.text=control.text
هیچ کاری صورت نمیده.
این که می فرمائین drag&drop کنم در واقع کاری که من میخوام بکنم drag&swap location هستش. برا اینه که از رویدادهای drag&drop استفاده نکردم.
اگه بازم فکر میکنید drag&drop بهتره خیلی ممنون میشم یه توضیحی بفرمائین.
باسلام
تمام مطالبی رو که دوستمون اشاره کردند درسته اما یه پیشنهادی هم من براتون می دم
ما وقتی کنترلی رو به صورت دینامیک ایجاد می کنیم یعنی از طریق کد نویسی ایجادش می کنیم
همونجا که ایجادش کردیم می تونیم رویدادهای متفاوت رو هم براشون ایجاد کنیم و در همان لحظه به هر تعداد از اونها رویداد ایجاد شده رو اختصاص بدیم :لبخند:
به این نمونه که محض روشن شدن قضیه درست کردم توجه کنین :


TextBox buttons = new TextBox(); buttons.Name = "btn"+i.ToString();
buttons.Size = new Size(99, 20);
buttons.Location = new Point(i * 50, i * 80);
buttons.Text = "btn"+i.ToString();
buttons.ForeColor = Color.DeepPink;
buttons.BackColor = Color.LimeGreen;
buttons.Show();
buttons.MouseHover += (senderObject, eventArgs) =>
{

MessageBox.Show(buttons.Name+" "+"مورد انتخابی شما عبارت است از ");


};
this.Controls.Add(buttons);

فقط کافیه با ماوس روی کنترلها اشاره کنین بدون کلیک و بدون انجام کاری دیگر ......:لبخند:

mh3242
سه شنبه 24 تیر 1393, 00:48 صبح
باسلام
تمام مطالبی رو که دوستمون اشاره کردند درسته اما یه پیشنهادی هم من براتون می دم
ما وقتی کنترلی رو به صورت دینامیک ایجاد می کنیم یعنی از طریق کد نویسی ایجادش می کنیم
همونجا که ایجادش کردیم می تونیم رویدادهای متفاوت رو هم براشون ایجاد کنیم و در همان لحظه به هر تعداد از اونها رویداد ایجاد شده رو اختصاص بدیم :لبخند:
به این نمونه که محض روشن شدن قضیه درست کردم توجه کنین :


TextBox buttons = new TextBox(); buttons.Name = "btn"+i.ToString();
buttons.Size = new Size(99, 20);
buttons.Location = new Point(i * 50, i * 80);
buttons.Text = "btn"+i.ToString();
buttons.ForeColor = Color.DeepPink;
buttons.BackColor = Color.LimeGreen;
buttons.Show();
buttons.MouseHover += (senderObject, eventArgs) =>
{

MessageBox.Show(buttons.Name+" "+"مورد انتخابی شما عبارت است از ");


};
this.Controls.Add(buttons);

فقط کافیه با ماوس روی کنترلها اشاره کنین بدون کلیک و بدون انجام کاری دیگر ......:لبخند:


khokhan جان خیلی زحمت کشیدی وقت گذاشتی دست شما و دوست عزیزمون plus درد نکنه ولی فکر کنم اشتباه متوجه شدی.
یا شاید هم من متوجه جواب نشدم.
مشکل رویداد mouse hover اینه که قبل از mouse move اتفاق می افته.
در هر صورت اصل قضیه:
این سناریو رو در نظر بگیر
یه پازل از تصویر. کاربر یه عکسی رو انتخاب میکنه و بعدش هم اون عکس به 4 قسمت تقسیم میشه. به صورت دینامیک یه آرایه 4تایی از picture box ها درست میشه و تو یه حلقه بهشون حافظه تخصیص داده میشه و خاصیت های
image
size
locatoin
....
هر کدومشون تو همون حلقه مقدار دهی میشن.
کار دیگه که تو همون حلقه انجام میشه اینه که رویداد های
mouse down
mouse move
mouse up
هر کدوم از picture box ها به (به ترتیب)

private void PicBox_MouseDownEvent(Object sender, MouseEventArgs e)

private void PicBox_MouseMoveEvent(Object sender, MouseEventArgs e)

private void PicBox_MouseUpEvent(Object sender, MouseEventArgs e)

منتصب میشن.
نکته:اگه مثلا 1000 تا picture box تو حلقه تعریف بشه، رویداد mouse move همشون یه تابع هستش و ....
خب در ادامه کارهایی صورت میگیره که به اصل ماجرا ربطی نداره تا میرسیم به
PicBox_MouseDownEvent
تو این رویداد کدهای:

StartY = Cursor.Position.Y;
StartX = Cursor.Position.X;
EndY = ((PictureBox)sender).Location.Y;
EndX = ((PictureBox)sender).Location.X;
TempPicBox = new PictureBox();
TempPicBox.Size = ((PictureBox)sender).Size;
TempPicBox.SizeMode = ((PictureBox)sender).SizeMode;
Bitmap TempBmp = new Bitmap(((PictureBox)sender).Image);
for (int i = 0; i < TempBmp.Size.Width; i++)
{
for (int j = 0; j < TempBmp.Size.Height; j++)
{
Color c = TempBmp.GetPixel(i, j);
Color newc = Color.FromArgb(50, c);
TempBmp.SetPixel(i, j, newc);
}
}
TempPicBox.Image = TempBmp;
this.Controls.Add(TempPicBox);


رو داریم. همونطوری که میبینی یه سری نقاط که از نامشون بر میاد چیکاره هستن رو تو یه سری متغیر سراسری ذخیره میکنیم و یه نمونه از شی انتخاب شده (که اون هم سراسری هستش) میسازیم و خلاصه یه سری عملیات دیگه هم روش انجام میدیم.

رویداد بعدی PicBox_MouseMoveEvent
کدهای این رویداد هم:

if (e.Button == MouseButtons.Left)
{
TempPicBox.BringToFront();
TempPicBox.Location = new Point(EndX + (Cursor.Position.X - StartX), EndY + (Cursor.Position.Y - StartY));
}


این چند خط هستن که کلا میکن اگه دکمه چپ موس پایین باشه ....

در نهایت کدهای رویداد PicBox_MouseUpEvent (که خدا ازش نگذره :عصبانی: هیچ رقمه باهام راه نمیاد:عصبانی++:) هستش که باید موارد
-آیا موس داخل محدوده فرم هست؟
-آیا موس روی یکی از picture box ها هست؟
رو چک کنه و اگه درست بود یه تابع به اسم swap رو صدا میکنه.
اعلان تابع swap:

private void Swap(PictureBox picbox1, PictureBox picbox2)

همونطور که معلومه این تابع زمان فراخونی باید دو تا picture box بهش بدی.
یکیشون همونیه که موس اونو نگه داشته بود (همونی که سه تا رویداد mousedown و mousemove و mouseup رو فراخونی کرده بود) که خیلی راحت با استفاده از sender میشه بهش دسترسی داشت. اما اون یکی picture box همونیه که رویداد mouseup از picture box قبلی روش اتفاق افتاده. این picture box رو من چجوری پیدا کنم؟ گیر من رو اینه.
کدهای تابع swap (با اینکه به موضوع ربطی نداره) به این صورته:

private void Swap(PictureBox picbox1, PictureBox picbox2) {
if (picbox1.Location != picbox2.Location)
{
Point p = picbox1.Location;
picbox1.Location = picbox2.Location;
picbox2.Location = p;
}
}
شرمنده خیلی حرف زدم. بازم خیلی ممنون از همتون که وقت میزارین.

plus
سه شنبه 24 تیر 1393, 01:23 صبح
شما اگه مسائل رو از هم جدا کنید حتما مشکل کار رو پیدا میکنید.
با Cursor.Position شما میتونید مختصات Cursor رو داشته باشید. با this.PointToClient (با فرض اجرای کد در فرم) شما مختصات موس بر حسب بالا سمت چپ Client Area ی فرم رو پیدا میکنید. و با this.GetChildAtPoint کنترل موجود روی اون نقطه رو پیدا میکنید.

Point pt = Cursor.Position;
Point clientPt = this.PointToClient(pt);
PictureBox pictireBox = this.GetChildAtPoint(clientPt) as PictureBox;

mh3242
سه شنبه 24 تیر 1393, 17:09 عصر
بله شما درست می فرمائین. اشتباه از من بوده.
خیلی دقت کردم متوجه شدم با کدی که شما دادین TempPicBox رو برام بر میگردونه. دلیلش هم این بود که تو MouseMove دستور
TempPicBox.BringToFront();
رو داشتم.
تو MouseUp قبل از کدهای شما از
TempPicBox.SendToBack();
استفاده کردم و همه چی درست شد.
خیلی ممنون از همه دوستان.