گفتگو هایی در باب سی شارپ

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اصولا نقطه رسم نمیشه. خط کشیده میشه. حالا Line یا Bezier بستگی به خودتون داره. فاصله ایجاد میشه، چون نقطه می کشید. باید نقطه ها رو وصل کنید بهم.

درباره ی پست بالا ، ممنون و بعد از این پیام میخونم
درباره ی رسم خط هم ممنون . کشیدم و درست شد (هر چند باز هم نقاط و فاصله ی کوچیکی میمونه ولی 90 درصدش درست شد)
حالا یه تکسچر (فایل png با ابعاد 16 در 16) درست کردم و تقریبا همون الگوریتمی که برای رسم خط بکار بردم ، برای این هم بکار بردم ولی مشکلش اینجاست که وقتی این تکسچر را میخواد رسم کنه ، یکنواخت رسم میکنه و در پیکسل های بعدی اش که موس را میکشم ، فضای خالیِ بینِ تکسچر رو پر نمیکنه . یه عکس میزارم تا بهتر متوجه شین :


1.JPG

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


کد:
        private Bitmap BitmapForGraphic;
        private Graphics GraphicForm;
        private List<Point> PointAllMouse;

        public FormTest()
        {
            InitializeComponent();
            this.BitmapForGraphic = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            this.GraphicForm = this.CreateGraphics();
            this.PointAllMouse = new List<Point>();
        }

        private void FormTest_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                    if (this.PointAllMouse.Count > 0)
                    {
                        Graphics graphicsInBitmap = Graphics.FromImage(this.BitmapForGraphic);
                        Bitmap bitmapTexture = new Bitmap(@"E:\2.png");
                        TextureBrush textureBrush = new TextureBrush(bitmapTexture);
                        Pen pen = new Pen(textureBrush, 16);
                        graphicsInBitmap.DrawLine(pen, this.PointAllMouse[this.PointAllMouse.Count - 1], e.Location);
                        this.GraphicForm.DrawImage(this.BitmapForGraphic, new Rectangle(new Point(0, 0), this.BitmapForGraphic.Size));
                    }
                    this.PointAllMouse.Add(e.Location);
            }
        }

البته رویداد MouseUp و یه رویداد دیگه هم کد داره ولی کد اصلی نیست که بماند
و این هم فایل تکسچر png با ابعاد 16 در 16 :


2.png

حالا سئوالم اینه که چجوری باید کد را تغییر داد تا با هر جابجایی موس ، دوباره توی همون پیکسل ، از اول بیاد و اون تکسچر را رسم کنه یا به عبارتی چجوری میشه فاصله هاشو پر کرد و توی اون فاصله هایی که موس را میکشیم ، باز هم همون تکسچر را رسم کنه یا به عبارتی ، چجوری مثل فتوشاپ ، یه تکسچر رو بصورت ممتد رسم کنه؟
دومین سئوال هم اینکه با اینکه تکسچرام (فایل png) ، رنگ قهوه ای هست ، ولی میشه کاری کرد که مثلا رنگ قهوه ای رو به رنگی که دلمون میخواد (مثلا رنگ قرمز) تبدیل کنه و تکسچر رو با رنگ قرمز رسم کنه؟
ممنون
 

the_king

مدیرکل انجمن
درباره ی پست بالا ، ممنون و بعد از این پیام میخونم
درباره ی رسم خط هم ممنون . کشیدم و درست شد (هر چند باز هم نقاط و فاصله ی کوچیکی میمونه ولی 90 درصدش درست شد)
حالا یه تکسچر (فایل png با ابعاد 16 در 16) درست کردم و تقریبا همون الگوریتمی که برای رسم خط بکار بردم ، برای این هم بکار بردم ولی مشکلش اینجاست که وقتی این تکسچر را میخواد رسم کنه ، یکنواخت رسم میکنه و در پیکسل های بعدی اش که موس را میکشم ، فضای خالیِ بینِ تکسچر رو پر نمیکنه . یه عکس میزارم تا بهتر متوجه شین :


مشاهده پیوست 112055

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


کد:
        private Bitmap BitmapForGraphic;
        private Graphics GraphicForm;
        private List<Point> PointAllMouse;

        public FormTest()
        {
            InitializeComponent();
            this.BitmapForGraphic = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            this.GraphicForm = this.CreateGraphics();
            this.PointAllMouse = new List<Point>();
        }

        private void FormTest_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                    if (this.PointAllMouse.Count > 0)
                    {
                        Graphics graphicsInBitmap = Graphics.FromImage(this.BitmapForGraphic);
                        Bitmap bitmapTexture = new Bitmap(@"E:\2.png");
                        TextureBrush textureBrush = new TextureBrush(bitmapTexture);
                        Pen pen = new Pen(textureBrush, 16);
                        graphicsInBitmap.DrawLine(pen, this.PointAllMouse[this.PointAllMouse.Count - 1], e.Location);
                        this.GraphicForm.DrawImage(this.BitmapForGraphic, new Rectangle(new Point(0, 0), this.BitmapForGraphic.Size));
                    }
                    this.PointAllMouse.Add(e.Location);
            }
        }

البته رویداد MouseUp و یه رویداد دیگه هم کد داره ولی کد اصلی نیست که بماند
و این هم فایل تکسچر png با ابعاد 16 در 16 :


مشاهده پیوست 112056

حالا سئوالم اینه که چجوری باید کد را تغییر داد تا با هر جابجایی موس ، دوباره توی همون پیکسل ، از اول بیاد و اون تکسچر را رسم کنه یا به عبارتی چجوری میشه فاصله هاشو پر کرد و توی اون فاصله هایی که موس را میکشیم ، باز هم همون تکسچر را رسم کنه یا به عبارتی ، چجوری مثل فتوشاپ ، یه تکسچر رو بصورت ممتد رسم کنه؟
دومین سئوال هم اینکه با اینکه تکسچرام (فایل png) ، رنگ قهوه ای هست ، ولی میشه کاری کرد که مثلا رنگ قهوه ای رو به رنگی که دلمون میخواد (مثلا رنگ قرمز) تبدیل کنه و تکسچر رو با رنگ قرمز رسم کنه؟
ممنون
هر Brush ای که بخواهید استفاده کنید مبنای رسم اش یک نقطه آغازین ئه که قابل تنظیمه. چون شما اون نقطه آغازین رو تغییر نمی دهید و ثابت میمونه اینطوری میشه. اون TextureBrush متد TranslateTransform داره. مقدار x و y ای که بهش بدید بصورت نسبی به همون اندازه جابجا میشه، 0, 0 یعنی جابجا نشه. و طبیعتا x و y اش میتونه اعداد منفی هم باشه.
اون this اضافی رو که لازم نیست می نویسید، ولی اشیاء ای که میسازید و لازمه Dispose بشوند رو نه با using بکار می برید و نه Dispose می کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
هر Brush ای که بخواهید استفاده کنید مبنای رسم اش یک نقطه آغازین ئه که قابل تنظیمه. چون شما اون نقطه آغازین رو تغییر نمی دهید و ثابت میمونه اینطوری میشه. اون TextureBrush متد TranslateTransform داره. مقدار x و y ای که بهش بدید بصورت نسبی به همون اندازه جابجا میشه، 0, 0 یعنی جابجا نشه. و طبیعتا x و y اش میتونه اعداد منفی هم باشه.
اون this اضافی رو که لازم نیست می نویسید، ولی اشیاء ای که میسازید و لازمه Dispose بشوند رو نه با using بکار می برید و نه Dispose می کنید.

ممنون استاد علی
اون خط رو به خط زیر تغییر دادم ولی بازم همون جوری هه :


کد:
                        graphicsInBitmap.DrawLine(pen, this.PointAllMouse[this.PointAllMouse.Count - 1], e.Location);
                        this.textureBrush.TranslateTransform(e.Location.X, e.Location.Y);
                        this.GraphicForm.DrawImage(this.BitmapForGraphic, new Rectangle(new Point(0, 0), this.BitmapForGraphic.Size));

باید چجوری تغییرش بدم؟
درباره ی this میدونم . کلا عادت به دقیق نویسی اشیاء دارم
درباره ی Dispose و using هم میدونم . این کدِ تمرینمه و کدِ رسمی نیست واسه همین نام متغییرها شاید کلا پرت و پلا باشه گاها یا باگ هایی که ازش خبر دارم هم داشته باشه و ...
ولی چیزی که باید Dispose بشه ، قطعا متغییر سراسری نیست دیگه (چون در زمان استفاده در زیر برنامه ی دیگه ، قابل دسترس نیست) ؟ شما آیا توصیه میکنید شی بیت مپ (اصلی و در صورت نیاز) ، بصورت سراسری تعریف بشه ولی شی گرافیک را بصورت محلی تعریف کنیم برای Dispose کردنش (بازم در صورت نیاز) ؟

یه سئوال دیگه اینکه میدونیم گرافیکِ رسم شده روی یک کنترل (بجز در رویداد paint) ، با تغییر وضعیتِ اون کنترل (مثل minimize و maximize و تغییر سایز و تغییر اسکرول اون کنترل و ...) پاک میشه و درباره باید اون بیت مپ رو روی اون کنترل رسم کرد . حالا یه رویدادی نیست (بجز paint) که یکی از این عملیاتی که باعث پاک شدن گرافیک مون میشه ، وجود داشته باشه تا هر بار داخل رویدادهای مختلف ، تابعی که عمل رسم مجدد گرافیک را انجام میده را فراخونی نکنیم و فقط داخل یک رویداد فراخونی کنیم؟
 
آخرین ویرایش:

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بجای اینکه نقاط رو با Dictionary نگهدارید یک Bitmap رو برای لایه رسم نگهدارید. برای پاک کردن از Bitmap هم CompositingMode رو در گرافیکی که بر اساس Bitmap میسازید SourceCopy کنید و با Brushes.Transparent و Pens.Transparent هر چی دایره و مربع بکشید و پر کنید ازش پاک میشه. اگه SourceOver بود چون Transparent ئه هیچ تاثیری نداشت ولی چون SourceCopy ئه خالیش می کنه.
اینکار روی پنجره و e.Graphics جواب نمیده چون بجای پاک شدن سیاه میشه ولی روی Bitmap ها جواب میده و پاک میشه.

ممنون استاد علی
این کار رو کردم ولی پاک نمیشه
کدش اینه :


کد:
        private Bitmap BitmapForGraphic;
        private Graphics GraphicForm;
        private Graphics graphicsInBitmap;
        private Rectangle RectEraser;

        public FormTest()
        {
            InitializeComponent();

            this.BitmapForGraphic = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            this.RectEraser = new Rectangle();
            this.GraphicForm = this.CreateGraphics();
            this.graphicsInBitmap = Graphics.FromImage(this.BitmapForGraphic);
        }

        private void FormTest_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                    this.RectEraser.X = e.X - 8;
                    this.RectEraser.Y = e.Y - 8;
                    this.RectEraser.Width = 16;
                    this.RectEraser.Height = 16;

                    this.graphicsInBitmap.CompositingMode = CompositingMode.SourceCopy;
                    this.graphicsInBitmap.FillRectangle(Brushes.Transparent, this.RectEraser);
                    this.GraphicForm.DrawImage(this.BitmapForGraphic, new Rectangle(new Point(0, 0), this.BitmapForGraphic.Size));
            }
        }

چجوری باید تغییر کنه؟
 

the_king

مدیرکل انجمن
ممنون استاد علی
اون خط رو به خط زیر تغییر دادم ولی بازم همون جوری هه :


کد:
                        graphicsInBitmap.DrawLine(pen, this.PointAllMouse[this.PointAllMouse.Count - 1], e.Location);
                        this.textureBrush.TranslateTransform(e.Location.X, e.Location.Y);
                        this.GraphicForm.DrawImage(this.BitmapForGraphic, new Rectangle(new Point(0, 0), this.BitmapForGraphic.Size));
باید چجوری تغییرش بدم؟

من در این کد چیزی درباره رسم textureBrush نمی بینم که نظری بدم.
درباره ی this میدونم . کلا عادت به دقیق نویسی اشیاء دارم
درباره ی Dispose و using هم میدونم . این کدِ تمرینمه و کدِ رسمی نیست واسه همین نام متغییرها شاید کلا پرت و پلا باشه گاها یا باگ هایی که ازش خبر دارم هم داشته باشه و ...
ولی چیزی که باید Dispose بشه ، قطعا متغییر سراسری نیست دیگه (چون در زمان استفاده در زیر برنامه ی دیگه ، قابل دسترس نیست) ؟ شما آیا توصیه میکنید شی بیت مپ (اصلی و در صورت نیاز) ، بصورت سراسری تعریف بشه ولی شی گرافیک را بصورت محلی تعریف کنیم برای Dispose کردنش (بازم در صورت نیاز) ؟
اونهایی که static تعریف می کنید رو بهتره و لازمه با رخدادی مثل Application.ApplicationExit یا FormClosing مدیریت کنید.
قطعا Bitmap ای که در طی پروسه برنامه مدام مورد استفاده است و تغییر ابعاد هم داده نمیشه رو بهتره سراسری تعریف کنید که حفظ بشه چون هر بار ایجاد کردنش به هر حال سربار داره و اما ایجاد کردن محلی اش ایراد فنی نیست.
شی Graphics اما کلا فرق می کنه، اصلا نباید طولانی نگهش دارید، اشتباهه که خیال کنید قابل نگهداری طولانی ئه. برای این منظور طراحی نشده که بخواهید در متغیر سراسری مقدارش رو در کل پروسه نگه دارید. طراحی شده برای استفاده موقتی و درست برخلاف BufferedGraphics، و استفاده اش هم همیشه گذرا است و باید سریع آزاد بشه، اینکه نگهداریش در متغیر سراسری باشه مهم نیست، مهمه اینه که هی شیء بهش بدید و بعد دوبار سریع آزادش کنید. سراسری بودن متغیر منافاتی با آزاد کردن شیء نداره که. مقدار جدید بهش بدید و بعد آزاد می کنید.

یه سئوال دیگه اینکه میدونیم گرافیکِ رسم شده روی یک کنترل (بجز در رویداد paint) ، با تغییر وضعیتِ اون کنترل (مثل minimize و maximize و تغییر سایز و تغییر اسکرول اون کنترل و ...) پاک میشه و درباره باید اون بیت مپ رو روی اون کنترل رسم کرد . حالا یه رویدادی نیست (بجز paint) که یکی از این عملیاتی که باعث پاک شدن گرافیک مون میشه ، وجود داشته باشه تا هر بار داخل رویدادهای مختلف ، تابعی که عمل رسم مجدد گرافیک را انجام میده را فراخونی نکنیم و فقط داخل یک رویداد فراخونی کنیم؟
پاک نمیشه، پاک شدن نتیجه اینه که رسم ای صورت گرفته. دیدید تا حالا نرم افزاری باگ داشته باشه و رد ماوس یا گرافیکی رو صفحه بمونه؟ چرا رد میمونه؟ چون رسم در جایی که Inavlidate شده صورت نگرفته. اگه رسم رنگ زمینه انجام میشد اونوقت به قول شما پاک می شد، ولی پاک نمیشه، رنگ زمینه مجددا رسم میشه.
اون پاک شدن به این دلیله که رسم رنگ Background انجام شده ولی رسم بعدی که در Paint باید انجام میشد صورت نگرفته. یک کنترل میتونه فاقد روال مجزا برای رسم زمینه باشه :
کد:
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
شما نیازی نیست با رویداد خاصی روال Paint رو مجدد فراخوانی کنید، به ندرت همچین چیزی لازم میشه. معمولا فقط Invalidate می کنید. در ضمن مواردی هست که میگید اگه کنترل تغییر ابعاد داده شد، باید حتما paint مجدد بشه :
کد:
SetStyle(ControlStyles.ResizeRedraw, true);
اصولا شما برای شیء ای که گرافیک اش بافر خاصی نداره و باید با Paint های مکرر ترسیم بشه Invalidate می کنید، نه رخداد Paint رو دستی ایجاد می کنید و نه متدی که رسم با Graphics مجزا رو انجام میده فراخوانی می کنید.
اما زمانی که خود Paint کاری بجز رسم یک بافر نداره و ترسیم خاصی انجام نمیده، اونوقت اول اون متدی که بافر رو بروز می کنه فراخوانی می کنید و بعدا Invalidate می کنید.
هیچوقت از داخل کد یک رخداد رخداد مرتبط دیگه ای رو فراخوانی نکنید، ترتیب فراخوانی رخداد ها که اهمیت داره رو بهم می زنید. رخداد برای اینه که شمایی که بیرون از بدنه یک شیء مثل Control هستید رو از یک موردی با خبر کنه، اگر داخل بدنه شی باشید اصلا به رخداد احتیاج ندارید، چون خودتون ایجاد کننده رخداد هستید، و به همین جهت ایجاد کردن رخداد جعلی منطقی نیست، روالی که اون رخداد باید انجام میداده رو باید اجرا کنید، نه اینکه رخداد جعلی ایجاد کنید. برای شیء ای که مثل Control بیرون از بدنه اش هستید رخداد ایجاد کردن مثل اینه که بگید صبح پاشم و بعدا حالا خودمو بیدار کنم.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
من در این کد چیزی درباره رسم textureBrush نمی بینم که نظری بدم.

سلام
ممنون استاد علی
کد کاملش اینه :


کد:
        private Bitmap BitmapForGraphic;
        private Graphics GraphicForm;
        private List<Point> PointAllMouse;
        private Bitmap bitmapTexture;
        private TextureBrush textureBrush;
        private Pen pen;
        private Graphics graphicsInBitmap;


        public FormTest()
        {
            InitializeComponent();

            this.BitmapForGraphic = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            this.GraphicForm = this.CreateGraphics();

            this.PointAllMouse = new List<Point>();
            this.bitmapTexture = new Bitmap(@"E:\2.png");
            this.textureBrush = new TextureBrush(bitmapTexture);
            this.pen = new Pen(textureBrush, 16);
            this.graphicsInBitmap = Graphics.FromImage(this.BitmapForGraphic);
        }

        private void FormTest_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                    if (this.PointAllMouse.Count > 0)
                    {
                        graphicsInBitmap.DrawLine(pen, this.PointAllMouse[this.PointAllMouse.Count - 1], e.Location);
                        this.textureBrush.TranslateTransform(e.Location.X, e.Location.Y);
                        this.GraphicForm.DrawImage(this.BitmapForGraphic, new Rectangle(new Point(0, 0), this.BitmapForGraphic.Size));
                    }
                    this.PointAllMouse.Add(e.Location);
            }
        }


اینکه نگهداریش در متغیر سراسری باشه مهم نیست، مهمه اینه که هی شیء بهش بدید و بعد دوبار سریع آزادش کنید. سراسری بودن متغیر منافاتی با آزاد کردن شیء نداره که. مقدار جدید بهش بدید و بعد آزاد می کنید.

منظورتون اینه که شیِ گرافیکِ سراسری تعریف شده را Dispose کنیم؟
اگه آره که اون شی مگه دیگه در زیر برنامه ی بعدی ، قابل استفاده هست؟ شی ای که Dispose بشه ، طبعا نباید در زیر برنامه ی دیگه قابل استفاده باشه و معمولا ارورِ زمان اجرا میده
بعد اینکه درباره ی تغییرِ رنگ ِ تکسچر در پست های قبلی گفته بودم ، چی؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلام
ممنون استاد علی
کد کاملش اینه :


کد:
        private Bitmap BitmapForGraphic;
        private Graphics GraphicForm;
        private List<Point> PointAllMouse;
        private Bitmap bitmapTexture;
        private TextureBrush textureBrush;
        private Pen pen;
        private Graphics graphicsInBitmap;


        public FormTest()
        {
            InitializeComponent();

            this.BitmapForGraphic = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            this.GraphicForm = this.CreateGraphics();

            this.PointAllMouse = new List<Point>();
            this.bitmapTexture = new Bitmap(@"E:\2.png");
            this.textureBrush = new TextureBrush(bitmapTexture);
            this.pen = new Pen(textureBrush, 16);
            this.graphicsInBitmap = Graphics.FromImage(this.BitmapForGraphic);
        }

        private void FormTest_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                    if (this.PointAllMouse.Count > 0)
                    {
                        graphicsInBitmap.DrawLine(pen, this.PointAllMouse[this.PointAllMouse.Count - 1], e.Location);
                        this.textureBrush.TranslateTransform(e.Location.X, e.Location.Y);
                        this.GraphicForm.DrawImage(this.BitmapForGraphic, new Rectangle(new Point(0, 0), this.BitmapForGraphic.Size));
                    }
                    this.PointAllMouse.Add(e.Location);
            }
        }
منظورتون اینه که شیِ گرافیکِ سراسری تعریف شده را Dispose کنیم؟
اگه آره که اون شی مگه دیگه در زیر برنامه ی بعدی ، قابل استفاده هست؟ شی ای که Dispose بشه ، طبعا نباید در زیر برنامه ی دیگه قابل استفاده باشه و معمولا ارورِ زمان اجرا میده
بعد اینکه درباره ی تغییرِ رنگ ِ تکسچر در پست های قبلی گفته بودم ، چی؟
اینکه تو چه جور متغیری نگهش دارید که مهم نیست، وقتی Dispose شد برای سری استفاده بعدی باید Graphics جدید بسازید. حالا متغیرش هر جا که میخواد باشه.
اساسا خود TextureBrush تغییر رنگ نمیده، باید Bitmap تون رو تغییر بدید و مجددا TextureBrush بسازید. برای تغییر رنگ Bitmap با نقاط زیاد هم بجای SetPixel می توانید با LockBits داده داخل Bitmap رو بریزید در یک آرایه و بعد اونجا هر پردازشی خواستید روی بایت ها انجام بدبد و بعد با UnlockBits برگردونید داخل Bitmap. نتیجه سریعتر از اینه که هی بخواهید با GetPixel و SetPixel رنگ بخونید و بنویسید.

اسامی فیلدهاتون هم اصولی نیست، سلیقه مطرح هست ولی اصول برای سادگی و خوانایی کد ئه. یکی کوچیک، یکی بزرگ، کسی کدتون رو ببینه تا تعریف رو نبینه متوجه نمیشه فیلد ئه، پروپرتی ئه. با _ هم که شروع نمی شوند.
کد:
        private BufferedGraphics _buffer;
        private List<Point> _pointAllMouse;
        private Bitmap _bitmapTexture;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DoubleBuffered = true;
            using (var context = new BufferedGraphicsContext())
            {
                using (var g = CreateGraphics())
                {
                    _buffer = context.Allocate(g, ClientRectangle);
                }
            }
            _buffer.Graphics.Clear(BackColor);
            this._pointAllMouse = new List<Point>();
            this._bitmapTexture = new Bitmap(@"E:\2.png");
        }

        private void DrawTexture(Point location)
        {
            var dst = new Rectangle(location.X - _bitmapTexture.Width / 2, location.Y - _bitmapTexture.Height / 2, _bitmapTexture.Width, _bitmapTexture.Height);
            var src = new Rectangle(Point.Empty, _bitmapTexture.Size);
            _buffer.Graphics.DrawImage(_bitmapTexture, dst, src, GraphicsUnit.Pixel);
            _pointAllMouse.Add(location);
            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            if (_buffer != null)
            {
                _buffer.Render(e.Graphics);
            }
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                DrawTexture(e.Location);
            }
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                DrawTexture(e.Location);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _buffer.Dispose();
            _buffer = null;
        }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
پاک نمیشه، پاک شدن نتیجه اینه که رسم ای صورت گرفته. دیدید تا حالا نرم افزاری باگ داشته باشه و رد ماوس یا گرافیکی رو صفحه بمونه؟ چرا رد میمونه؟ چون رسم در جایی که Inavlidate شده صورت نگرفته. اگه رسم رنگ زمینه انجام میشد اونوقت به قول شما پاک می شد، ولی پاک نمیشه، رنگ زمینه مجددا رسم میشه.
اون پاک شدن به این دلیله که رسم رنگ Background انجام شده ولی رسم بعدی که در Paint باید انجام میشد صورت نگرفته. یک کنترل میتونه فاقد روال مجزا برای رسم زمینه باشه :
کد:
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
شما نیازی نیست با رویداد خاصی روال Paint رو مجدد فراخوانی کنید، به ندرت همچین چیزی لازم میشه. معمولا فقط Invalidate می کنید. در ضمن مواردی هست که میگید اگه کنترل تغییر ابعاد داده شد، باید حتما paint مجدد بشه :
کد:
SetStyle(ControlStyles.ResizeRedraw, true);
اصولا شما برای شیء ای که گرافیک اش بافر خاصی نداره و باید با Paint های مکرر ترسیم بشه Invalidate می کنید، نه رخداد Paint رو دستی ایجاد می کنید و نه متدی که رسم با Graphics مجزا رو انجام میده فراخوانی می کنید.
اما زمانی که خود Paint کاری بجز رسم یک بافر نداره و ترسیم خاصی انجام نمیده، اونوقت اول اون متدی که بافر رو بروز می کنه فراخوانی می کنید و بعدا Invalidate می کنید.
هیچوقت از داخل کد یک رخداد رخداد مرتبط دیگه ای رو فراخوانی نکنید، ترتیب فراخوانی رخداد ها که اهمیت داره رو بهم می زنید. رخداد برای اینه که شمایی که بیرون از بدنه یک شیء مثل Control هستید رو از یک موردی با خبر کنه، اگر داخل بدنه شی باشید اصلا به رخداد احتیاج ندارید، چون خودتون ایجاد کننده رخداد هستید، و به همین جهت ایجاد کردن رخداد جعلی منطقی نیست، روالی که اون رخداد باید انجام میداده رو باید اجرا کنید، نه اینکه رخداد جعلی ایجاد کنید. برای شیء ای که مثل Control بیرون از بدنه اش هستید رخداد ایجاد کردن مثل اینه که بگید صبح پاشم و بعدا حالا خودمو بیدار کنم.

ممنون استاد علی
اول اینکه ، یکی در میون به پست ام جواب ندادین . اگه بدین ، ممنون میشم
یکی پست 764 هه . یکی هم قضیه ی تغییر رنگ تکسچر که پرسیده بودم (چون قابلیت ویرایش بعد از نیم ساعت از بین میره ، احتمالا دومین پستی که بعدش میزارم رو نمیبینین)
ممنون میشم اونا رو هم جواب بدین

بعد اینکه من این جوابی که دادین رو قشنگ درک نکردم
اول اینکه من گفتم توی کدوم رویداد باید کدِ پاک شدن (یا به قول درست تر ، رسمِ دوباره ی گرافیکِ بیت مپ در کنترل مورد نظر) را انجام بدم؟
دوم اینکه اون دو تا کدی که دادین برای چی هه؟ برای پاک کردنه؟
سوم اینکه اگه برای پاک کردنه ، خوب باید (موقع تغییر سایز یا minimize و هر عملی که باعث پاک شدن گرافیک رسم شده میشه) توی یک رویدادی این کد را نوشت. درسته؟ سئوالم اینه که اون رویداد کدوم رویداده؟ یعنی یه رویدادی میخوام که مشترک باشه برای تمام رویدادهایی که رسم رو پاک میکنه (یا به قول درست تر و به قول شما ، رسم پشت زمینه ی اون کنترل رو انجام میده که باعث پاک شدن گرافیک رسم شده مون میشه) وگرنه میتونم توی چندین رویداد مختلف ، رسم ام را فراخونی کنم
چهارم اینکه بهتره برای رسم ، توی بیت مپی رسم کنیم (یا توی بیت مپی ، رسمی را پاک کنیم) و بعد اون بیت مپ رو توی گرافیکِ اون کنترل رسم کنیم دیگه. درسته؟ در این صورت ، بیت مپ یا گرافیکِ مربوط به اون بیت مپ که تابع Invalide نداره تا رسمِ داخلش رو پاک کنه . اگه هم متد Invalide در اون کنترل رو صدا بزنیم برای پاک کردن که چندان اصولی نیست چون ممکنه چندین بیت مپ (لایه) در داخل اون کنترل رسم شده باشه که همه را پاک میکنه
پنجم اینکه شما گفتین Invalide ، رسم میکنه؟!! Invalide که پاک میکنه تا جایی که میدونم
شیشم اینکه الان نباید از درون یک رویداد ، رویدادِ دیگه ای را فراخونی کرد؟ یعنی منظورتون اینه که بجای اینکه رویدادی را فراخونی کنیم ، تابع درست کنیم و اون تابع رو از هر رویدادی که دلمون خواست فراخونی کنیم؟ ما که دیوانه شدیم :green: یکی از اساتیدها (یکی نه ؛ اغلب) میاد توی آموزشش ، یه رویداد رو از توی رویداد دیگه صدا میزنه . بعد شما (که قطعا نظرتون معتبرتره) یه چیز دیگه میگین . ای کاش یکی مثل شما یه آموزشی درست میکرد از پایه تا کسایی که آموزش میبینن ، از بیخ و بن ، اصولی نوشتن کد رو یاد بگیرن (ما که پر از اشکالیم)
 

the_king

مدیرکل انجمن
ممنون استاد علی
اول اینکه ، یکی در میون به پست ام جواب ندادین . اگه بدین ، ممنون میشم
یکی پست 764 هه . یکی هم قضیه ی تغییر رنگ تکسچر که پرسیده بودم (چون قابلیت ویرایش بعد از نیم ساعت از بین میره ، احتمالا دومین پستی که بعدش میزارم رو نمیبینین)
ممنون میشم اونا رو هم جواب بدین

در مورد پاک کردن توضیح داده بودم ولی کدتون رو اصلا مطابق چیزی که گفتم تغییر نداده بودید که، شما رسم تون در Paint بود؟ نه، Graphics ساخته بودید و مستقل رسم می کردید و گفتم هم که Graphics خودش زمینه اش پاک نمیشه، سیاه میشه. بعدم میگید اینکار رو کردم ولی پاک نمیشه. نکردید که.
تغییر رنگ رو هم جواب دادم، باید Bitmap تون رو عوض کنید. TextureBrush تغییر رنگ نمیده.

بعد اینکه من این جوابی که دادین رو قشنگ درک نکردم
اول اینکه من گفتم توی کدوم رویداد باید کدِ پاک شدن (یا به قول درست تر ، رسمِ دوباره ی گرافیکِ بیت مپ در کنترل مورد نظر) را انجام بدم؟
کدی که نوشتم رو ببینید.


دوم اینکه اون دو تا کدی که دادین برای چی هه؟ برای پاک کردنه؟
نه، برای رسم کردنه، مشخصه که، اجراش کنید معلومه چیکار می کنه. اما اساس کار همینه، یک بافر دارید، حالا هر چند تا لایه Bitmap جدا هم برای لایه سازی داشته باشید به کنار. این بافر سر جاش میمونه.
سوم اینکه اگه برای پاک کردنه ، خوب باید (موقع تغییر سایز یا minimize و هر عملی که باعث پاک شدن گرافیک رسم شده میشه) توی یک رویدادی این کد را نوشت. درسته؟

شما وقتی سایز گرافیک تون عوض شد باید Bitmap های لایه ها و بافر تون از نو ایجاد بشه. قبلی رو موقت نگهدارید، جدید رو با سایز جدید بسازید و اینو داخلش رسم کنید تا ترسیم ها از دست نره.
سئوالم اینه که اون رویداد کدوم رویداده؟ یعنی یه رویدادی میخوام که مشترک باشه برای تمام رویدادهایی که رسم رو پاک میکنه (یا به قول درست تر و به قول شما ، رسم پشت زمینه ی اون کنترل رو انجام میده که باعث پاک شدن گرافیک رسم شده مون میشه) وگرنه میتونم توی چندین رویداد مختلف ، رسم ام را فراخونی کنم
رسم در بافر که رخداد نیست، متد ئه، رخداد چیزی ئه که شی به شما اطلاع میده، شما دارید رسم می کنید، این رخداد نیست. هر چند تا متد خواستید بسازید برای رسم های متفاوت در بافر. اما رسم بافر روی پنجره فقط و فقط با همون Paint ئه. هیچ جای دیگه Graphics ای که روی پنجره رسم می کنه نسازید.
چهارم اینکه بهتره برای رسم ، توی بیت مپی رسم کنیم (یا توی بیت مپی ، رسمی را پاک کنیم) و بعد اون بیت مپ رو توی گرافیکِ اون کنترل رسم کنیم دیگه. درسته؟
اگه بافر ندارید آره، ولی کلا BufferedGraphics بهتر از Bitmap ئه، اما برای رسم شفاف که بخواهید زیرش دیده بشه و بقول خودتون پاک کنید Bitmap باید باشه.

در این صورت ، بیت مپ یا گرافیکِ مربوط به اون بیت مپ که تابع Invalide نداره تا رسمِ داخلش رو پاک کنه . اگه هم متد Invalide در اون کنترل رو صدا بزنیم برای پاک کردن که چندان اصولی نیست چون ممکنه چندین بیت مپ (لایه) در داخل اون کنترل رسم شده باشه که همه را پاک میکنه
اصلا کنترل حافظه نداره که، Invalidate کردن دست شما نیست که بگید اصلا نمیکنم که پاک نشه، به هر حال چیزی از روی فرم رد شه رخ میده. اصولیه.
پنجم اینکه شما گفتین Invalide ، رسم میکنه؟!! Invalide که پاک میکنه تا جایی که میدونم
پاک می کنه؟ اسمش Invalidate ئه، نه Clear ئه و نه Delete. توضیح دادم. نمیخونید. روال رسم نیست که پاک کنه. نمیدونم از کجا میدونید ولی اشتباهه. پاک نمی کنه.
شیشم اینکه الان نباید از درون یک رویداد ، رویدادِ دیگه ای را فراخونی کرد؟ یعنی منظورتون اینه که بجای اینکه رویدادی را فراخونی کنیم ، تابع درست کنیم و اون تابع رو از هر رویدادی که دلمون خواست فراخونی کنیم؟ ما که دیوانه شدیم :green: یکی از اساتیدها (یکی نه ؛ اغلب) میاد توی آموزشش ، یه رویداد رو از توی رویداد دیگه صدا میزنه . بعد شما (که قطعا نظرتون معتبرتره) یه چیز دیگه میگین . ای کاش یکی مثل شما یه آموزشی درست میکرد از پایه تا کسایی که آموزش میبینن ، از بیخ و بن ، اصولی نوشتن کد رو یاد بگیرن (ما که پر از اشکالیم)
شما ظاهرا متد رو با رخداد قاطی می کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اینکه تو چه جور متغیری نگهش دارید که مهم نیست، وقتی Dispose شد برای سری استفاده بعدی باید Graphics جدید بسازید. حالا متغیرش هر جا که میخواد باشه.
اساسا خود TextureBrush تغییر رنگ نمیده، باید Bitmap تون رو تغییر بدید و مجددا TextureBrush بسازید. برای تغییر رنگ Bitmap با نقاط زیاد هم بجای SetPixel می توانید با LockBits داده داخل Bitmap رو بریزید در یک آرایه و بعد اونجا هر پردازشی خواستید روی بایت ها انجام بدبد و بعد با UnlockBits برگردونید داخل Bitmap. نتیجه سریعتر از اینه که هی بخواهید با GetPixel و SetPixel رنگ بخونید و بنویسید.

اسامی فیلدهاتون هم اصولی نیست، سلیقه مطرح هست ولی اصول برای سادگی و خوانایی کد ئه. یکی کوچیک، یکی بزرگ، کسی کدتون رو ببینه تا تعریف رو نبینه متوجه نمیشه فیلد ئه، پروپرتی ئه. با _ هم که شروع نمی شوند.
کد:
        private BufferedGraphics _buffer;
        private List<Point> _pointAllMouse;
        private Bitmap _bitmapTexture;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DoubleBuffered = true;
            using (var context = new BufferedGraphicsContext())
            {
                using (var g = CreateGraphics())
                {
                    _buffer = context.Allocate(g, ClientRectangle);
                }
            }
            _buffer.Graphics.Clear(BackColor);
            this._pointAllMouse = new List<Point>();
            this._bitmapTexture = new Bitmap(@"E:\2.png");
        }

        private void DrawTexture(Point location)
        {
            var dst = new Rectangle(location.X - _bitmapTexture.Width / 2, location.Y - _bitmapTexture.Height / 2, _bitmapTexture.Width, _bitmapTexture.Height);
            var src = new Rectangle(Point.Empty, _bitmapTexture.Size);
            _buffer.Graphics.DrawImage(_bitmapTexture, dst, src, GraphicsUnit.Pixel);
            _pointAllMouse.Add(location);
            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            if (_buffer != null)
            {
                _buffer.Render(e.Graphics);
            }
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                DrawTexture(e.Location);
            }
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                DrawTexture(e.Location);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _buffer.Dispose();
            _buffer = null;
        }

ممنون استاد علی
میشه این کد رو فقط با کلاس هایی که من بیشتر آشنام بنویسین (کلاس هایی مثل bitmap و graphics و ...) ؟ یعنی کلاس هایی مثل BufferedGraphics و BufferedGraphicsContext رو درگیر نکنین؟
اون جوری دقیق تر متوجه میشم
اگه نمیشه که هیچ چی
 

the_king

مدیرکل انجمن
ممنون استاد علی
میشه این کد رو فقط با کلاس هایی که من بیشتر آشنام بنویسین (کلاس هایی مثل bitmap و graphics و ...) ؟ یعنی کلاس هایی مثل BufferedGraphics و BufferedGraphicsContext رو درگیر نکنین؟
اون جوری دقیق تر متوجه میشم
اگه نمیشه که هیچ چی
 

پیوست ها

  • WindowsFormsApplication2.zip
    79.9 کیلوبایت · بازدیدها: 4

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f

خیلی ممنونم استاد علی . حالا خیلی قشنگ تر متوجه شدم
ولی یه سئوال همچنان باقی هست
متد Erase ای که نوشتین ، عین الگوریتمی هست که من در پست 764 نوشتم . هیچ فرق خاصی نداره . از یه شیِ بیت مپ ، شی گرافیک جدید گرفتین و CompositingMode از اون شیِ گرافیک رو با CompositingMode.SourceCopy مقدار دادین و بعد اون شیِ بیت مپ را با براش Brushes.Transparent پر کردین که باعث شد تا پاک (Transparent) بشه و بعد در رویداد paint (با فراخونی invalid) ، اون شیِ بیت مپ (همه ی اشیاء بیت مپ) رو در گرافیکِ فرم ، رسم کردین
منم دقیقِ دقیق ، همین کار رو کردم ولی واسه ی من چرا پاک نمیشه
----------------------------------
بعد اینکه اصولی اینه که توی رویداد paint ، فقط اون شیِ بیت مپ را در گرافیکِ اون کنترل رسم کنیم؟ تازه متوجه شدم
 

the_king

مدیرکل انجمن
خیلی ممنونم استاد علی . حالا خیلی قشنگ تر متوجه شدم
ولی یه سئوال همچنان باقی هست
متد Erase ای که نوشتین ، عین الگوریتمی هست که من در پست 764 نوشتم . هیچ فرق خاصی نداره . از یه شیِ بیت مپ ، شی گرافیک جدید گرفتین و CompositingMode از اون شیِ گرافیک رو با CompositingMode.SourceCopy مقدار دادین و بعد اون شیِ بیت مپ را با براش Brushes.Transparent پر کردین که باعث شد تا پاک (Transparent) بشه و بعد در رویداد paint (با فراخونی invalid) ، اون شیِ بیت مپ (همه ی اشیاء بیت مپ) رو در گرافیکِ فرم ، رسم کردین
منم دقیقِ دقیق ، همین کار رو کردم ولی واسه ی من چرا پاک نمیشه

کد که متوجه نمیشه کی اونو نوشته، شما CreateGraphics رو برای دسترسی به چی نوشته بودید؟ پنجره فرم، this.CreateGraphics، و گفتم که پنجره زمینه اش پاک نمیشه، سیاه میشه. من Graphics رو برای دسترسی به چی نوشته بودم، یک شی Bitmap. تو کل کد من هیچ Graphics ای برای دسترسی به پنجره ایجاد نشده.
بعد اینکه اصولی اینه که توی رویداد paint ، فقط اون شیِ بیت مپ را در گرافیکِ اون کنترل رسم کنیم؟ تازه متوجه شدم
این اصول نیست، لازمه کد شما این بوده، همه طراحی ها که بر اساس Bitmap نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کد که متوجه نمیشه کی اونو نوشته، شما CreateGraphics رو برای دسترسی به چی نوشته بودید؟ پنجره فرم، this.CreateGraphics، و گفتم که پنجره زمینه اش پاک نمیشه، سیاه میشه. من Graphics رو برای دسترسی به چی نوشته بودم، یک شی Bitmap. تو کل کد من هیچ Graphics ای برای دسترسی به پنجره ایجاد نشده.

این اصول نیست، لازمه کد شما این بوده، همه طراحی ها که بر اساس Bitmap نیست.


ممنون استاد علی
آها فهمیدم
مشکل کد در پست 764 ، در قسمت شیِ بیت مپ نیست . یعنی در شیِ بیت مپ ، عملیات ترنسپرنت (پاک کردن) رو انجام میده ولی وقتی میگیم همون شیِ بیت مپ رو (که قسمتی از موس روش رد و کلیک میشه ، اون قسمت ترنسپرنت میشه) دوباره در گرافیکِ form رسم کن ، اون قسمتی که ترنسپرنت شد را دوباره روی رنگِ قبلی (مثلا قرمز) رسم میکنه پس بنابراین باز هم همون رنگ زیرش یعنی رنگ قرمز نمایش میده . (که حواسم به این موضوع نبود)
برای حل این مشکل ، باید قبل از رسمِ مجددِ اون بیت مپ در کنترل (در فرم) ، باید اون رسم رو پاک کنیم.
یعنی اگه کد رویداد FormTest_MouseMove در پست 764 را به شکل زیر تغییر بدیم ، درست میشه :


کد:
        private void FormTest_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.RectEraser.X = e.X - 8;
                this.RectEraser.Y = e.Y - 8;
                this.RectEraser.Width = 16;
                this.RectEraser.Height = 16;

                this.graphicsInBitmap.CompositingMode = CompositingMode.SourceCopy;
                this.graphicsInBitmap.FillRectangle(Brushes.Transparent, this.RectEraser);
                this.Refresh();
                this.GraphicForm.DrawImage(this.BitmapForGraphic, new Rectangle(new Point(0, 0), this.BitmapForGraphic.Size));
            }
        }

ولی این کد Refresh ، باعث میشه خیلی سو سو بزنه . بجای Refresh ، یک کدِ سبک تری نیست که رسم رو سریعتر پاک کنه و باعث سو سو زدن اش نشه؟
البته الگوریتم درست تر همونی هه که شما در پروژه ی دیروزتون دادین ولی خواستم بدونم کلا کد سبک تری برای پاک کردن رسم وجود داره؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کد که متوجه نمیشه کی اونو نوشته، شما CreateGraphics رو برای دسترسی به چی نوشته بودید؟ پنجره فرم، this.CreateGraphics، و گفتم که پنجره زمینه اش پاک نمیشه، سیاه میشه. من Graphics رو برای دسترسی به چی نوشته بودم، یک شی Bitmap. تو کل کد من هیچ Graphics ای برای دسترسی به پنجره ایجاد نشده.

این اصول نیست، لازمه کد شما این بوده، همه طراحی ها که بر اساس Bitmap نیست.

همون الگوریتمی که شما نوشتین ، بهترین بود
یعنی از لحاظ اصولی اش هم نادیده بگیریم ، بهترین کد برای پاک و رسم مجدد ، کد Invalidate کردن هست که با این کار ، باز هم باید در رویداد paint ، کدهامون رو بنویسیم . البته سوسو میزنه که باید DoubleBuffered مربوط به اون کنترل رو فعال کرد (که در کدِ پستِ بالا ، با فعال کردن این خاصیت هم باز سوسو میزنه)
-------------------------
حالا منظورم این بود که توی چیزها و کدها و الگوریتم هایی که نیاز به رسم بیت مپ دارن ، اصولی اینه که توی رویداد paint ، فقط اون شیِ بیت مپ را در گرافیکِ اون کنترل رسم کنیم؟ و کلا هر کدی که نیاز نباشه همون اول چیزی رسم بشه (مثلا وقتی نیاز باشه با زدن یک دکمه یا کشیدن موس و ... ، چیزی رسم بشه) . چون در این صورت رسمی رو مستقیما اگه در رویداد paint رسم کنیم ، موقع لود اون فرم ، اون رسم در اون کنترل ، انجام میشه دیگه
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
این تابع وقتی دومین بار یا به بعد اجرا میشه ، بخاطر dispose کردن متغییر brush ، ارور میده :

کد:
        private void EraseFromBitmap(Bitmap targetBitmap, Rectangle eraseRegion)
        {
            using (Graphics graphicTargetBitmap = Graphics.FromImage(targetBitmap))
            {
                graphicTargetBitmap.CompositingMode = CompositingMode.SourceCopy;
                using (Brush brush = Brushes.Transparent)
                {
                    graphicTargetBitmap.FillRectangle(brush, eraseRegion);
                }
            }
            this.Invalidate();
        }

شما قبلا گفته بودین اعضای استاتیک کلاس Brushes ، بصورت مشترکی با ویندوز ، شی رو استفاده میکنه (یا یه چیزی شبیه همین گفته بودین) . دلیل این ارور برای اجرای بعدی ، همین مشترک بودن این براش با ویندوز هه؟
 

the_king

مدیرکل انجمن
این تابع وقتی دومین بار یا به بعد اجرا میشه ، بخاطر dispose کردن متغییر brush ، ارور میده :

کد:
        private void EraseFromBitmap(Bitmap targetBitmap, Rectangle eraseRegion)
        {
            using (Graphics graphicTargetBitmap = Graphics.FromImage(targetBitmap))
            {
                graphicTargetBitmap.CompositingMode = CompositingMode.SourceCopy;
                using (Brush brush = Brushes.Transparent)
                {
                    graphicTargetBitmap.FillRectangle(brush, eraseRegion);
                }
            }
            this.Invalidate();
        }

شما قبلا گفته بودین اعضای استاتیک کلاس Brushes ، بصورت مشترکی با ویندوز ، شی رو استفاده میکنه (یا یه چیزی شبیه همین گفته بودین) . دلیل این ارور برای اجرای بعدی ، همین مشترک بودن این براش با ویندوز هه؟
بله، کلا اشیاء ای که مستقیم و غیر مستقیم سازنده شون نیستید مسئولیت نابودی شون رو هم ندارید، اشیاء مشترکی مثل Brushes و SystemBrushes باید همیشه در دسترس باشند، using و Dispose برای اونها کاربردی نداره.
حالا منظورم این بود که توی چیزها و کدها و الگوریتم هایی که نیاز به رسم بیت مپ دارن ، اصولی اینه که توی رویداد paint ، فقط اون شیِ بیت مپ را در گرافیکِ اون کنترل رسم کنیم؟ و کلا هر کدی که نیاز نباشه همون اول چیزی رسم بشه (مثلا وقتی نیاز باشه با زدن یک دکمه یا کشیدن موس و ... ، چیزی رسم بشه) . چون در این صورت رسمی رو مستقیما اگه در رویداد paint رسم کنیم ، موقع لود اون فرم ، اون رسم در اون کنترل ، انجام میشه دیگه
عرض کردم خدمتتون، اصولی وجود نداره. در هر موردی با توجه به شرایط و نیاز کد روشی رو پیاده سازی می کنید که نتیجه بهتری داشته باشه. اغلب کنترل های پیچیده روی فرم اگه بخواهید تغییری رو روال رسم شون بدید پرپر زدن رو دارند، نه به این خاطر که روش شون اشتباه بوده، به این دلیل که وقتی شما روال رسم رو تغییر می دید شرایط و نیاز کد تغییر کرده و روش قبلی دیگه خوب جواب نمیده.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله، کلا اشیاء ای که مستقیم و غیر مستقیم سازنده شون نیستید مسئولیت نابودی شون رو هم ندارید، اشیاء مشترکی مثل Brushes و SystemBrushes باید همیشه در دسترس باشند، using و Dispose برای اونها کاربردی نداره.

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

ممنون
حالا برای اینکه مثل فتوشاپ ، تکسچرمون رو وقتی میکِشیم برای رسم کردن ، بصورت خط ممتد رسم کنه ، باید بین فاصله ی پیکسل های دو نقطه رو هم دونه دونه ، اون تکسچر رو رسم کنم تا پر بشه؟
البته این فاصله ای که میافته بخاطر اینه که پردازنده دیگه کششِ بیشتر از این رو نداره و موقع رسم ، به اندازه ی قدرتِ یه هسته ی کامل رو درگیر میکنه ولی فتوشاپ وظیفه رو بر دوش کارت گرافیک میندازه . درسته؟
البته باز هم شنیدم در wpf ، رسم گرافیک با directx و بر عهده ی کارت گرافیک میافته که بار پردازنده رو کم میکنه و همین احتمالا باید باعث بشه با همین الگوریتم ، در wpf ، موقع رسم تکسچر ، خط ممتد نشون داده بشه (چون سریعتر رسم انجام میشه توسط کارت گرافیک) . البته با wpf و زبان xaml کار نکردم و بلد نیستم .
نمیدونم چه لزومی به یه زبان دیگه برای کار با گرافیک بود؟! خوب با همین سی شارپ ، مایکروسافت قابلیت های wpf را توی win form انجام میداد . چه لزومی به یه زبان دیگه باز بود؟!
 

the_king

مدیرکل انجمن
ممنون
حالا برای اینکه مثل فتوشاپ ، تکسچرمون رو وقتی میکِشیم برای رسم کردن ، بصورت خط ممتد رسم کنه ، باید بین فاصله ی پیکسل های دو نقطه رو هم دونه دونه ، اون تکسچر رو رسم کنم تا پر بشه؟

منطقیه. البته فتوشاپ هم الزاما پیوسته نیست، Spacing داره.

البته این فاصله ای که میافته بخاطر اینه که پردازنده دیگه کششِ بیشتر از این رو نداره و موقع رسم ، به اندازه ی قدرتِ یه هسته ی کامل رو درگیر میکنه ولی فتوشاپ وظیفه رو بر دوش کارت گرافیک میندازه . درسته؟
کارت گرافیکی در هر حال درگیر میشه، اما تفاوت اصلی اینجا است که موتور گرافیکی فتوشاپ خیلی با +GDI ئه NET. فرق داره.

البته باز هم شنیدم در wpf ، رسم گرافیک با directx و بر عهده ی کارت گرافیک میافته که بار پردازنده رو کم میکنه و همین احتمالا باید باعث بشه با همین الگوریتم ، در wpf ، موقع رسم تکسچر ، خط ممتد نشون داده بشه (چون سریعتر رسم انجام میشه توسط کارت گرافیک) . البته با wpf و زبان xaml کار نکردم و بلد نیستم .
نمیدونم چه لزومی به یه زبان دیگه برای کار با گرافیک بود؟! خوب با همین سی شارپ ، مایکروسافت قابلیت های wpf را توی win form انجام میداد . چه لزومی به یه زبان دیگه باز بود؟!
چیزهایی که میگید اصلا ربطی بهم نداره، ترکیب کردنی هم نیستند، وابسته بهم هم نیستند. WPF و Win Form دو سیستم پردازشی متفاوت دارند، هیچکدوم هم زبان نیستند. #C هم نه مربوط به WPF ئه و نه Win Form. هر زبانی هم ممکنه از WPF یا Win Form پشتیبانی کنه، اساسا ربطی به زبان نداره. XAML هم برای مشخص کردن محتوای اینترفیس ئه، با همون ساختار XML، مثل HTML. زبان برنامه نویسی نیست، و مستقل از زبانی هم هست که برای برنامه نویسی همراه با WPF بکار می برید. و #C یا هر زبان برنامه نویسی دیگری هم نمی توانست جایگزین XAML و کاربردش باشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون استاد علی
هر چند خیلی توجیه نشدم که چرا سی شارپ نمیتونست جایگزین Xaml بشه
-----------------
یه سئوال اینکه ساده ترین روشی که بشه یه شکلی که ساختیم و رسم کردیم (مثلا یه مستطیلی رو داخل یه بیت مپ رسم کردیم) ، این شکل (مستطیل) رو بتونیم تغییر شکل بدیم مثلا 45 درجه همون شکل رو (نه اینکه یه شکل جدید دیگه) بچرخونیم ، چیه؟ یا حتی خودِ شیِ بیت مپ را میشه تغییر شکل داد؟
شاید بگین با پروپرتی Transform در اون شیِ گرافیک ولی من با ماتریکس ها آشناییتی ندارم و طرز کارش رو بلد نیستم . ساده تر از این روش ، وجود داره؟ یه نمونه ی کد ساده (خیلی ساده . مثلا یه مستطیلی رسم شه که بعدش 45 درجه چرخش پیدا کنه) میذارین؟ اگه میذارین ، لطفا به ساده ترین شکل ممکن باشه که متوجه بشم
ممنون
 

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

بالا