مشکل در ترسیم اشکال در #c

mahtab2009

Member
سلام
من تو محیط ویژوال به زبان #C برای ترسیم به مشکل برخوردم.
یه PictureBox دارم که می خوام ترسیمات روی اون نمایش داده بشه ولی نمی خوام مستقیم روی خود PictureBox عمل رسم انجام بشه. یه متغیر از نوع Bitmap معرفی کردم که شکل رسم شده رو به اون نسبت میدم و بعد هر چی توی اون Bitmap هست در PictureBox نمایش داده میشه.
مشکل اینه که چون رسم در MouseMove مربوط به PictureBox انجام میشه اگه بخوام مثلا یه مستطیل بدون پرکننده رسم کنم موقع درگ ماوس مدام مستطیل رسم میشه تا به نقطه انتهایی و MouseUp برسم. لطفا کدی که نوشتم رو بخونین و راهنماییم کنین.
خیلی خیلی ممنون
کد:
void New()
        {
            pic = null;
            pic = new Bitmap(pictureBox1.Width, pictureBox1.Height);
            g = Graphics.FromImage(pic);
            g.FillRectangle(Brushes.White, new Rectangle(0, 0, pic.Width, pic.Height));
            pictureBox1.Image = pic;
        }
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            toolStripStatusLabel1.Text = e.X+","+e.Y+" px";
            try
            {
                if (draw)
                {
                    x1 = e.X;
                    y1 = e.Y;
                    width = Math.Abs(startX - x1);
                    height = Math.Abs(startY - y1);
                    switch (state)
                    {
                        case "FillRect":
                            b.Color = background.BackColor;
                            g.FillRectangle(b, startX, startY, width, height);
                            g.DrawRectangle(p, startX, startY, width, height);
                            pictureBox1.Image = pic;
                            break;
                        case "Rect":
                            g.DrawRectangle(p, startX, startY, x1, y1);
                            pictureBox1.Image = pic;
                            break;
                        case "FillCirc":
                            break;
                        case "Circ":
                            break;
                        case "Arc":
                            break;
                        case "Line":
                            break;
                        case "Pencil":
                            break;
                        case "Text":
                            break;
                        case "Eraser":
                            break;
                    }
                }
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            draw = true;
            startX = e.X;
            startY = e.Y;
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            draw = false;
        }
 

mahtab2009

Member
یه مشکل جدید پیدا کردم، دو تا کد مثل هم رو یه بار برای گزینه delete در منوی edit و یه بار برای کلید delete روی صفحه نوشتم. وقتی از منو delete میکنم مشکلی نیست ولی بعد از پاک کردن توسط delete روی صفحه دیگه نمی تونم شکلی رسم کنم یعنی چی؟؟؟؟؟؟
کد:
private void del_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Do you want to remove image?", "Remove", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                g.FillRectangle(Brushes.White, new Rectangle(0, 0, pic.Width, pic.Height));
                pictureBox1.Image = pic;
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Do you want to remove image?", "Remove", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                g.FillRectangle(Brushes.White, new Rectangle(0, 0, pic.Width, pic.Height));
                pictureBox1.Image = pic;
            }
        }
 

the_king

مدیرکل انجمن
یک کار درست رو بد موقعی انجام می دهید، حافظه تصویری شما Bitmap ئه، نه Graphics، شی Graphics
برای نمایش های لحظه ای طراحی شده، مثل دستمال کاغذی می مونه، وقتی لازم اش داشتید از جعبه
بکشیدش بیرون، استفاده اش که کردید باید بریزیدش دور، نگه ندارید. همان لحظه ای که قراره رسم کنید
شیء Graphics را بسازید، و رسم که تمام شد رهایش کنید تا نابود بشه. برای دفعه بعد یک نمونه جدید اش
رو بسازید.

شیوه درست استفاده از Graphics اینه، اینطوری دیگه اشتباهی از نمونه قبلی استفاده نمی کنید :
کد:
            using (Graphics g = Graphics.FromImage(pic))
            {
.
.
.
                g.Flush();
            }

پارامتر های case ئه Rect رو هم اشتباه نوشتید.بجای width و height از x1, y1 استفاده کردید.

کد:
                if (draw)
                {
                    x1 = e.X;
                    y1 = e.Y;
                    width = Math.Abs(startX - x1);
                    height = Math.Abs(startY - y1);
                    pic2 = (Bitmap)pic.Clone();
                    using (Graphics g = Graphics.FromImage(pic2))
                    {
                        switch (state)
                        {
                            case "FillRect":
                                b.Color = background.BackColor;
                                g.FillRectangle(b, startX, startY, width, height);
                                g.DrawRectangle(p, startX, startY, width, height);
                                break;
                            case "Rect":
                                g.DrawRectangle(p, startX, startY, width, height);
                                break;
                            case "FillCirc":
                                break;
                            case "Circ":
                                break;
                            case "Arc":
                                break;
                            case "Line":
                                break;
                            case "Pencil":
                                break;
                            case "Text":
                                break;
                            case "Eraser":
                                break;
                        }
                        g.Flush();
                    }
                    pictureBox1.Image = pic2;
                }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            pic = (Bitmap)pic2.Clone();
            draw = false;
        }
 
آخرین ویرایش:

mahtab2009

Member
سلام
جناب king خیلی خیلی ممنون بابت راهنماییتون. اگه ممکنه در یه مورد دیگه هم کمکم کنید.
قبل از اینکه کدها رو اونجوری که شما گفتین تغییر بدم برای open file کد زیر رو نوشته بودم ، مشکل این بود که روی عکس زوم نمیشد و عکس به اندازه PictureBox من نمایش داده نمیشد.
کد:
private void openfile_Click(object sender, EventArgs e)
        {
            if (of.ShowDialog() == DialogResult.OK)
            {
                pictureBox1.Image = Image.FromFile(of.FileName);
                pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;
                pic = new Bitmap(pictureBox1.Image);
                g = Graphics.FromImage(pic);
            }
        }
حالا سؤالم اینه که همون کاری که در مورد g گفتین رو اینجا هم باید انجام داد؟ و دیگه اینکه از وقتی کد زیر رو به MouseUp اضافه کردم بعد از openfile اگه روی صفحه کلیک کنم با خطا مواجه میشم.
کد:
pic = (Bitmap)pic2.Clone();
سؤال دیگه ام اینه که برای رسم کمان چه جوری با توابع ریاضی مقدار زاویه شروع و مقدار چرخش رو همزمان با حرکت ماوس محاسبه کنم؟
ممنون میشم کمکم کنید.
 

the_king

مدیرکل انجمن
سلام
جناب king خیلی خیلی ممنون بابت راهنماییتون. اگه ممکنه در یه مورد دیگه هم کمکم کنید.
قبل از اینکه کدها رو اونجوری که شما گفتین تغییر بدم برای open file کد زیر رو نوشته بودم ، مشکل این بود که روی عکس زوم نمیشد و عکس به اندازه PictureBox من نمایش داده نمیشد.
کد:
private void openfile_Click(object sender, EventArgs e)
        {
            if (of.ShowDialog() == DialogResult.OK)
            {
                pictureBox1.Image = Image.FromFile(of.FileName);
                pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;
                pic = new Bitmap(pictureBox1.Image);
                g = Graphics.FromImage(pic);
            }
        }
حالا سؤالم اینه که همون کاری که در مورد g گفتین رو اینجا هم باید انجام داد؟
شما اندازه pic رو زمانی تعیین کرده اید که تازه کلاس در حال ایجاد شدن است. اگر با اندازه PictureBox
تطابق نداره به همین دلیله که اندازه PictureBox بعدا تغییر می کنه اما pic رو در همون اندازه قبلی ثابت نگه داشته اید.
PictureBox رخداد SizeChanged داره، ازش برای ساختن مجدد pic در ابعاد جدید PictureBox استفاده کنید.

اگر می خواهید از قابلیت BackgroundImageLayout استفاده کنید، pictureBox1.Image را مشخص نکنید،
بجایش pictureBox1.BackgroundImage را مشخص کنید.

و دیگه اینکه از وقتی کد زیر رو به MouseUp اضافه کردم بعد از openfile اگه روی صفحه کلیک کنم با خطا مواجه میشم.
کد:
pic = (Bitmap)pic2.Clone();
کد تان را کامل ندیده ام اما احتمال دارد که pic2 برابر null باشد :
کد:
            if (pic2 != null)
            {
                pic = (Bitmap)pic2.Clone();
            }

سؤال دیگه ام اینه که برای رسم کمان چه جوری با توابع ریاضی مقدار زاویه شروع و مقدار چرخش رو همزمان با حرکت ماوس محاسبه کنم؟
ممنون میشم کمکم کنید.
رسم را باید در سه مرحله انجام دهید، یک متغیر مثل level داشته باشید که اگر 0 باشد می خواهید نقطه مرکز کمان
را مشخص کنید. بعد که روی یک نقطه کلیک کردید 1 می شود و باید شعاع کمان (یک نقطه دیگر) و در واقع
نقطه شروع کمان را مشخص کنید. وقتی روی نقطه دیگری کلیک کردید 2 شود و حالا باید نقطه پایانی کمان
را مشخص کنید که این یکی مثل نقطه قبلی هر جایی نخواهد بود :
مختصات نقطه مرکز کمان را دارید، فرضا x0, y0
مختصات نقطه شروع کمان را هم دارید، فرضا x1, y1
مختصات نقطه فعلی ماوس هم که فرضا x, y است.
شعاع کمان که فاصله دو نقطه است، ((Math.Sqrt(Math.Pow(x0 - x1, 2) + Math.Pow(y0 - y1, 2 فرضا r
نسبت (y1 - y0) / (x1 - x0) را حساب کنید و ازش Math.Atan بگیرید. این می شود زاویه شروع کمان. فرضا n،
البته بر حسب رادیان، نه درجه. باید تقسیم بر Math.PI و ضربدر 180 اش کنید تا بشود درجه.

نسبت (y - y0) / (x - x0) را حساب کنید و ازش Math.Atan بگیرید. این می شود زاویه نقطه فعلی ماوس، فرضا m
نقطه انتهایی کمان هم با توجه به موقعیت ماوس می شود Cos(m) * r + x0, Sin(m) * r + y0
طبیعتا اگر بخواهید میزان نسبی زاویه رو بدست بیاورید، مقدار n را از m کسر خواهید کرد.

تا آنجایی که یادم هست یک شرط را هم باید اضافه کنید وگرنه Atan صرفا برای 180 درجه زاویه را درست جواب
می دهد و برای 180 درجه دیگر زاویه را برعکس اعلام می کند.
 

جدیدترین ارسال ها

بالا