PDA

View Full Version : رسم شکل با click و drag کردن mouse



programmermp
جمعه 29 دی 1385, 20:00 عصر
سلام

اول از همه این رو بگم که دو بار سرچ کردم هیچی تو سایت که کار بکنه یا هدف من رو

تامین بکنه پیدا نکردم

حالا سئوالم اینه که می خوام وقتی کاربر روی فرم کلیک می کنه و ماوس رو drag می کنه

و در نهات ماوس رو رها می کنه مختصات نقطه ابتدا و انتهای ماوس رو در نظر بگیره

و بر اساس اون یک شکل مثل مستطیل در اون مختصات رسم کنه

مثلا اگه در محیط ویندوز روی دسکتاپ ماوس رو کلیک و drag کنید و رها کنید در حالت

drag کردن یک مستصیل نقطه چین می بینید من می خواهم همین حالت باشه و

مستطیل رو ی فرم رسم بشه


البته من با دو دستور زیر مختصات ماوس رو در دوحالت بدست می یارم

در حالت drag و در حالت کلیک کردن : x=control.mouseposition.x
y=control.mouseposition.y

و از دستوارت زیر هم می شه برای رسم اشکال گرافیکی استفاده کرد

Dim GrPath As New GraphicsPath
GrPath.AddRectangle(New RectangleF(New PointF(x1, y1), New SizeF(x1, y1)))



اما مشکل اینجاست که نمی دونم چکار کنم که مستطیل رسم شده مختصاتش دقیقا

مختصاتی باشه که کاربر با drag کردن ماوس انتخاب می کنه و شکل رسم شده روی فرم

رسم بشه

لطفا در این زمینه به من کمک کنید

با تشکر

programmermp
شنبه 30 دی 1385, 10:16 صبح
کسی نمی خواهد یه کمکی کنه

تقریبا تمام قسمتهاش در امده فقط یک قسمتش مونده

با تشکر

leilav_1984
شنبه 30 دی 1385, 11:07 صبح
من این کارو قبلا انجام دادم
اینجوری که یه مستطیل از نقطه ای که MouseDown اتفاق می افته تا نقطه MouseMove کشیدم

programmermp
شنبه 30 دی 1385, 12:09 عصر
من این کارو قبلا انجام دادم
اینجوری که یه مستطیل از نقطه ای که MouseDown اتفاق می افته تا نقطه MouseOver کشیدم

می شه یک لطفی کنید به ما هم کمک کنید

ممنون می شم اگه به من هم بگید چطوری می شه این کار رو کرد

با تشکر

Neeloofar
شنبه 30 دی 1385, 18:42 عصر
سلام

من اصلا در مورد گرافیک در VS 2005 چیزی نمیدونستم ول به لطف دوستان خصوصا آقای حامد مصافی (BlackDal) (در پستهای قبل) تشویق شدیم و یک چیزایی یاد گرفتم. (با وی بی 6 خیلی فرق داره)
من فقط یک راهنمایی میکنم چون خودم در VS2005 تازه یاد گرفتم. (ولی اگر VB6.0 بود نمونه های زیادی دارم.)

این کدها رو در فرم کپی کنید و در فرم موس را DragDrop کنید.



Dim BeginDraw As Boolean = False
Dim X As Integer, Y As Integer

Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) HandlesMe.MouseDown
BeginDraw = True
X = e.X
Y = e.Y
End Sub

Private Sub DrawRectangle(ByVal ToX As Integer, ByVal ToY As Integer)
'Dim myBrush As New System.Drawing.SolidBrush(System.Drawing.Color.Red )
Dim formGraphics As System.Drawing.Graphics
formGraphics = Me.CreateGraphics()
formGraphics.Clear(Me.BackColor)
formGraphics.DrawRectangle(Pens.Black, New Rectangle(X, Y, ToX, ToY))
'myBrush.Dispose()
formGraphics.Dispose()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Load
End Sub

Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) HandlesMe.MouseMove
If BeginDraw Then
DrawRectangle(e.X, e.Y)
End If
End Sub

Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) HandlesMe.MouseUp
BeginDraw = False
End Sub


این ادیتور نمدونم چرا فاصله ها رو به هم میچسبونه.:متفکر:
شاید بتونید خودتون کامل کنید.:چشمک:

programmermp
شنبه 30 دی 1385, 19:28 عصر
با سلام نیلوفر خانم

بسیار از کدتون ممنونم

ولی یه سئوال من اگه بخواهم این کار رو بجای فرم رو ی عکس انجام بدم باید ان عکس رو

به گمانم به عنوان backgroundimage فرم قرار بدم چون این کار رو با picturebox که خواستم

انجام بدم دیدم چون picturebox از رویداد mouseeventarge فرم استفاده می کنه شکل

مستطیل به جای تصویر رو ی فرم و زیر تصویر کشیده می شه

راه دیگری به نظر شما نداره

Neeloofar
شنبه 30 دی 1385, 21:56 عصر
سلام

فرقی نمیکنه. شما در تابع DrawRectangle به جای هر Me اسم picturebox رو بگذار (مثلاPicturebox1 ).
بعد به جای اینکه از روال های Form1_MouseUp , Form1_MouseDown, Form1_MouseMove استفاده کنید از روالهای مربوط به PictureBox1 استفاده کنید.

PictureBox1_MouseDown
PictureBox1_MouseUp
PictureBox1_MouseMove



Dim BeginDraw As Boolean = False
Dim X As Integer, Y As Integer

Private Sub DrawRectangle(ByVal ToX As Integer, ByVal ToY As Integer)
Dim formGraphics As System.Drawing.Graphics
formGraphics = PictureBox1.CreateGraphics()
formGraphics.Clear(PictureBox1.BackColor)
formGraphics.DrawRectangle(Pens.Black, New Rectangle(X, Y, ToX, ToY))
formGraphics.Dispose()
End Sub

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
BeginDraw = True
X = e.X
Y = e.Y
End Sub
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
If BeginDraw Then
DrawRectangle(e.X, e.Y)
End If
End Sub
Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
BeginDraw = False
End Sub

' OK !?

programmermp
شنبه 30 دی 1385, 22:24 عصر
با سلام

نیلوفر خانم من تست کردم نشد

به کد زیر نگاه کنید



Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
BeginDraw = True
X = e.X
Y = e.Y
End Sub

اگه دقت کنید می بینید که در داخل پرانتز چی نوشته و برای چی نمی شه


e As System.Windows.Forms.MouseEventArgs

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

روی فرم مستطیل رسم می شه نمی دونم باید چی کار کنم

لطفا کمک کنید

Payam Moradi
شنبه 30 دی 1385, 22:48 عصر
کد ایشون موردی نداره!

شما یک فرم جدید ایجاد کن.
یک PictureBox1 به فرم اضافه کن.
سپس کدهای مربوط Picture رو از بالا عینا کپی و در فرم بگذارید.

مراحل بالا رو به ترتیب انجام بده.

نکنه شما Handle رو به Form دادی؟


Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
BeginDraw = True
X = e.X
Y = e.Y
End Sub




اگر کلیه رویدادهای مربوط به PictureBox1 به Me هندل شده باشد خب معلومه رو فرم میکشه!

programmermp
شنبه 30 دی 1385, 23:08 عصر
با تشکر از شما

من همه کار ها رو درست انجام دادم

ببین من یک فرم جدید ایجاد کردم بعد یک picture box گذاشتم روی فرم بعد یک عکس رو

توی خاصیت image مربوط به picturebox از منوی پروپرتیز ادرس دهی کردم

بعد کدهای بالا رو کپی کردم و بعد هم وقتی ماوس رو drag کردم روی عکس یک دفعه

عکس ناپدید می شه و فقط شکل مستطیل که در اثر درگ کردن ماوس ایجاد شده باقی

ماند

فکر کنم این خاصیت که عکس ناپدید می شه به خاطر کد زیر باشه درسته


formGraphics.Clear(PictureBox1.BackColor)

خوب حالا نظرتون در این باره چیه

با تشکر

Neeloofar
یک شنبه 01 بهمن 1385, 01:11 صبح
سلام

خب علت بکار بردن خط بالا اینه که وقتی موس در حال حرکت هست مربع های متعددی کشیده نشه. خط بالا را حذف کرده و امتحان کنید.

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

حالا بعد خط بالا قرار بده:

Dim formGraphics As System.Drawing.Graphics
formGraphics = PictureBox1.CreateGraphics()
formGraphics.Clear(PictureBox1.BackColor)
PictureBox1.Image = PictureBox2.Image
formGraphics.DrawRectangle(Pens.Black, New Rectangle(X, Y, ToX, ToY))
formGraphics.Dispose()


میتونی این خط رو هم اصلا برداری:

formGraphics.Clear(PictureBox1.BackColor)

میگم من زیاد با ابزارهای گرافیکی دات نت کار نکردم. ولی اگه به نتیجه ای رسیدم اینجا مطرح میکنم.

programmermp
یک شنبه 01 بهمن 1385, 09:20 صبح
سلام نیلوفر خانم

من به خدا خیلی شرمندم این همه سئوال می کنم

ببخشید

من این کار رو کردم عکس جواب داد و لی مستطیلی که رسم می شه بعد از release یا

همان mouse up ناپدید می شه باقی نمی مونه

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

یک مستطیل با همان مشخصات رسم کنه فکر کنم همین راهش باشه

بازم خیلی ممنونم از حوصله و پاسخگویی شما:تشویق: :تشویق:

Neeloofar
یک شنبه 01 بهمن 1385, 13:51 عصر
سلام

این دیگه ردخور نداره. امیدوارم بیخیال ماشی!

1) یک فرم جدید باز کن
2) سه تا PictureBox به ترتیب PictureBox1 و PictureBox2 و PictureBox3 ایجاد کن.
3)اندازه اولی بزرگ باشه (چون میخوای عکس رو انتخاب کنید). اندازه دومی خیلی کوچیک باشه(مهم نیست). اندازه سومی هم به میزان چهارچوب انتخابی باشه.
4) تصویر اصلی را در PictureBox2 لود کن. (خصوصیت Image در Properties)
5) این کدها رو عینا در فرم کپی کن.



Dim BeginDraw As Boolean = False
Dim X As Integer, Y As Integer
Dim W As Integer, H As Integer

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
BeginDraw = True
X = e.X
Y = e.Y
End Sub

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
If BeginDraw Then
Dim formGraphics As System.Drawing.Graphics
Dim r As Rectangle = New Rectangle(X, Y, (e.X - X), (e.Y - Y))
formGraphics = PictureBox1.CreateGraphics()
PictureBox1.Image = PictureBox2.Image
Application.DoEvents()
formGraphics.DrawRectangle(Pens.Black, r)
formGraphics.Dispose()
End If
End Sub

Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
BeginDraw = False
W = e.X
H = e.Y
Dim r1 As Rectangle
r1.X = X
r1.Y = Y
r1.Width = W - X
r1.Height = H - Y
Dim r2 As Rectangle
r2.X = 0
r2.Y = 0
r2.Width = W - X
r2.Height = H - Y
Dim formGraphics As System.Drawing.Graphics
formGraphics = PictureBox3.CreateGraphics()
formGraphics.Clear(PictureBox3.BackColor)
formGraphics.DrawImage(PictureBox1.Image, r2, r1, GraphicsUnit.Pixel)
Application.DoEvents()
formGraphics.Dispose()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
PictureBox1.Image = PictureBox2.Image
End Sub


6) برنامه را اجرا و در PictureBox1 کلیک و دراگ کن. وقتی موس رها میشه نتیجه انتخاب در PictureBox3 نشون داده میشه!
7) این هفتمی که از همه مهمتره نگو دیگه ایراد داره.:لبخند:

من کدها رو اصلاح کردم و یک جاهایی تغییر دادم.

فقط یک ایراد کوچیک داره اونم در حالت سلکت برعکس یعنی پایین به بالا مربع کشیده نمیشه. اونم با ریاضیات خودت حل کن.


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

امیدوارم به مقصدودت رسیده باشی:چشمک:

leilav_1984
یک شنبه 01 بهمن 1385, 14:26 عصر
می شه یک لطفی کنید به ما هم کمک کنید

ممنون می شم اگه به من هم بگید چطوری می شه این کار رو کرد

با تشکر

در این برنامه نمونه من روشم رو اجرا کردم
البته با C# هستش ولی زیاد فرقی با VB.Net نداره. با این حال اگه مشکلی بود بگین تا توضیح بدم.

Neeloofar
یک شنبه 01 بهمن 1385, 16:20 عصر
سلام من کد leilav_1984 (http://www.barnamenevis.org/forum/member.php?u=11882) رو تبدیل کردم با کد خودم یک چیزی بدست آوردم و نتیجه جالبی بدست اومد. اگر برعکس بکشی عکس هم بر عکس انتخاب میشه. مراحلی که در پست قبلی گفتم تکرار کنید و به جای کدهای بالا کدهای ذیل را در فرم قرار دهید.



Private mouseDownPoint As Point
Private mouseMovePoint As Point
Private rectangle As Rectangle
Private pen As Pen

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
If (e.Button = Windows.Forms.MouseButtons.Left) Then
Me.mouseDownPoint = New Point(e.X, e.Y)
End If
End Sub

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
If (e.Button = Windows.Forms.MouseButtons.Left) Then
Me.mouseMovePoint = New Point(e.X, e.Y)
Dim num1 As Integer = Math.Min(mouseDownPoint.X, mouseMovePoint.X)
Dim num2 As Integer = Math.Min(mouseDownPoint.Y, mouseMovePoint.Y)
Dim num3 As Integer = Math.Max(mouseDownPoint.X, mouseMovePoint.X)
Dim num4 As Integer = Math.Max(mouseDownPoint.Y, mouseMovePoint.Y)
rectangle = New Rectangle(num1, num2, (num3 - num1), (num4 - num2))
Dim graphics1 As Graphics = Graphics.FromHwnd(PictureBox1.Handle)
PictureBox1.Image = PictureBox2.Image
Application.DoEvents()
pen = New Pen(Color.Gray, 1)
pen.DashStyle = Drawing2D.DashStyle.Dash
graphics1.DrawRectangle(pen, rectangle)
End If
End Sub

Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
If (e.Button = Windows.Forms.MouseButtons.Left) Then
Dim r1 As Rectangle
r1.X = mouseDownPoint.X
r1.Y = mouseDownPoint.Y
r1.Width = e.X - mouseDownPoint.X
r1.Height = e.Y - mouseDownPoint.Y
Dim r2 As Rectangle
r2.X = 0
r2.Y = 0
r2.Width = Math.Abs(mouseDownPoint.X - e.X)
r2.Height = Math.Abs(mouseDownPoint.Y - e.Y)
Dim formGraphics As System.Drawing.Graphics
formGraphics = PictureBox3.CreateGraphics()
formGraphics.Clear(PictureBox3.BackColor)
formGraphics.DrawImage(PictureBox1.Image, r2, r1, GraphicsUnit.Pixel)
Application.DoEvents()
formGraphics.Dispose()
End If
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
PictureBox1.Image = PictureBox2.Image
End Sub


دیگه از این کاملتر نمیشه.
به لطف همه دوستان ما هم با ابزارهای گرافیکی دات نت آشنا شدیم.:چشمک:

programmermp
یک شنبه 01 بهمن 1385, 19:07 عصر
سلام و خیلی خیلی ممنون از زحمات شما

بخصوص نیلوفر خانم که واقعا ما رو خجالت دادن :خجالت: :خجالت: :خجالت: :خجالت:


حالا یک سئوال دیگه (عجب ادم پر رویی ها بازم می خواهد سئوال کنه):عصبانی: :عصبانی:


حالا می خواهم قسمت که انتخاب شده با مستطیلی که روش کشیدیم رو به عنوان

یک imag در نظر بگیریم و ذخیره کنیم

یعنی قسمت های دیگه که توی قسمت انتخاب شده نیستند از image موقع ذخیره

حذف بشند دقیقا مثل کاری که با ابزار crop فتوشاپ انجام می دیم

(فکر کنم اخرش یک فتوشاپ کوچیک بسازیم تا روی شرکت adobe رو کم کنیم):لبخند: :لبخند: :لبخند:

اگه منظورم رو متوجه نشدید بگید تا بیشتر توضیح بدم

با تشکر فراوان

Neeloofar
یک شنبه 01 بهمن 1385, 21:09 عصر
باید راهی پیدا کرد تا تصویری که توسط formGraphics در PictureBox3 ترسیم میشه به Image تبدیل کرد تا بشه ذخیره کرد.
من که خودم کشتم نتوستم پیدا پیدا کنم.:ناراحت:
ولی اگر نتیجه ای گرفتم اینجا مطرح میکنم.

از بقیه دوستان هم درخواست میشه اگر اطلاعاتی در این مورد دارند دریغ نکنند.

Neeloofar
یک شنبه 01 بهمن 1385, 22:47 عصر
خیلی ممنون
مسئله اینه که PictureBox3.Image دارای GetPixel نیست و تصویر نقاشی شده در این کنترل توسط آبجکت formGraphics رو نمیتونم به یک آبجکت مثلا Bitmap ست کنم.
مشکل اساسی ایناست که نمیشه تصویر رسم شده توسط formGraphics (که از نوع System.Drawing.Graphics هست) رو تبدیل به یک ایمیج کنم. (نه با گرفتن پیکسل نه ست کردن در یک بیت مپ، در هر دو حالت Nothing یا Null برمیگردونه).
MSDN رو زیر و رو کردم ... .

Sub Zero
یک شنبه 01 بهمن 1385, 23:08 عصر
این PictureBox3.Image تصویرش رو از یه جا اورده دیگه اگه همینطوره پس یه کپی ازش بگیرید ( خط اول)

یه Bimap تعریف کن و تویه حلقه For تو در تو پیکسلهای محدوده انتخاب شده رو توی Bimap جدید بریز مثلا اگه نقطه انتخاب شده ابتدا برابر (100,100) و نقطه انتخاب شده انتها برابر ( 200,250) باشه:

Dim Timage As New Bitmap(PictureBox3.Image)
Dim Img2 As New Bitmap(100, 150)
For i = 0 To 100
For j = 0 To 150
Img2.SetPixel(i, j, Timage.GetPixel(i, j))
Next 'j
Next 'i
1- در اوردن ابعاد باخودت
2- ذخیره فایل هم باخودت

Neeloofar
یک شنبه 01 بهمن 1385, 23:18 عصر
بازم ممنون

ولی بازم مسئله اینه که علیرغم دیدن یک تصویر در PictureBox بازم متد Image اون برابر Null هست.(یا Nothing)
و هنگام اجرای این خط

کد:

Dim Timage As New Bitmap(PictureBox3.Image)
خطای ذیل مشاهده مشده میشه:

کد:

Object reference not set to an instance of an object.
وتوضیح MSDN:

A NullReferenceException occurs when you try to reference an object in your code that does not exist.

انگار چیزی که System.Drawing.Graphics میکشه جزو Imageها یا Handle به حساب نمی آد.

البته پاک کردن تاپیک خودتون رو نشانه رعایت قوانین سایت میدونم و شما سعی خودت کردی و متشکرم.

programmermp
دوشنبه 02 بهمن 1385, 17:12 عصر
سلام

کس دیگری از دوستان

نظری در رابطه با این موضوع نداره

یکی کاره ما رو راه بندازه:قهقهه: :قهقهه: :قهقهه:

با تشکر از دوستان