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

the_king

مدیرکل انجمن
ممنون
زمینه ی transparent منظورمه .
مثل یه همچین کدی :


کد:
            PictureBox currentPictureBox = sender as PictureBox;
            e.Graphics.DrawEllipse(new Pen(Color.Red, 4f), new Rectangle(new Point(0, 0), new Size(currentPictureBox.ClientSize.Width, currentPictureBox.ClientSize.Height)));

اما حالا در متد OnPaint مربوط به PictureBox . کد بالا ، در رویداد Paint مربوط به PictureBox بود.
باعث میشه بقیه ی جاهاش که پر رنگ آمیزی نشده (مثل وسط دایره در کد بالا) ، transparent و شفاف بمونه و پشت کنترلش مشخص باشه . اما همچین چیزی برای کنترل دکمه ، امکان پذیر نیست (البته با Flat کردن Style اش تا حدودی امکان پذیر هست ولی مشکلات خودش را داره)
از این مثالی که میزنید چیزی دستگیرم نشد.
شما یک پروژه جدید بسازید، اون PictureBox ای که میگید شفاف ئه و پشت کنترل اش مشخص ئه رو کد نویسی کنید و چند تا کنترل از انواع مختلف پشتش قرار بدید. اگر نتیجه داد پروژه zip شده رو پیوست کنید تا بررسی کنم و بگم فرقش با دکمه در چیه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
از این مثالی که میزنید چیزی دستگیرم نشد.
شما یک پروژه جدید بسازید، اون PictureBox ای که میگید شفاف ئه و پشت کنترل اش مشخص ئه رو کد نویسی کنید و چند تا کنترل از انواع مختلف پشتش قرار بدید. اگر نتیجه داد پروژه zip شده رو پیوست کنید تا بررسی کنم و بگم فرقش با دکمه در چیه.

ممنون
آو . بله درست میگین!
اما من توی اتوپلی ، میتونستم picture های png را بصورت همون transparent که بودن ، وارد کنم و کنترل های زیرش هم مشخص بودن (در قسمت هایی که alpha ی مربوط به فایل png ام به همون اندازه کمتر بود یا به عبارتی transparent بود)
الان این کار توی سی شارپ ، با همین دو تکنیکی که گفتین ، فقط قابل انجام هه؟ یعنی مثل اتوپلی ، هیچ گزینه ی ساده ای برای transparent کردن ، نداره و فقط باید تکنیک زد؟
 

the_king

مدیرکل انجمن
ممنون
آو . بله درست میگین!
اما من توی اتوپلی ، میتونستم picture های png را بصورت همون transparent که بودن ، وارد کنم و کنترل های زیرش هم مشخص بودن (در قسمت هایی که alpha ی مربوط به فایل png ام به همون اندازه کمتر بود یا به عبارتی transparent بود)
الان این کار توی سی شارپ ، با همین دو تکنیکی که گفتین ، فقط قابل انجام هه؟ یعنی مثل اتوپلی ، هیچ گزینه ی ساده ای برای transparent کردن ، نداره و فقط باید تکنیک زد؟
تعجب کردم وقتی در مورد PictureBox گفتید. در خیلی از برنامه ها و حتی زبان های برنامه نویسی مثل Visual Basic 6 یک سری از کنترل ها از اساس بصورت بدون پنجره (Windowless) طراحی میشوند که اصولا کنترل های Focus پذیری نیستند، مگر اینکه خود محیط شون کلا کاری با کنترل های استاندارد ویندوز نداره و Focus رو شبیه سازی کرده باشه. مخصوصا برای برنامه هایی که تعداد کنترل گرافیکی زیادی دارند این کنترل های بدون پنجره بیشتر کاربرد داره. مشکل در شیشه ای کردن پنجره بود، وقتی پنجره ای در کار نباشه که دیگه صورت مساله حذف شده. کنترل های Windowless اصلا پنجره ای برای خودشون ندارند که حالا بخوان برای شیشه ای شدنش فکری کنند. به همین جهت به سادگی روی بخشی از پنجره زمینه شون رسم می شوند و برای شفاف بودنشون هم طبعا مشکلی نیست :
کد:
    using System.Windows.Forms.VisualStyles;
    using System.Drawing.Imaging;

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            DoubleBuffered = true;
        }

        private class MyControl
        {
            private Rectangle _bounds;
            private Control _parent;
            private bool _hover;
            private bool _down;
            private string _text;

            public string Text
            {
                get => _text;
                set
                {
                    _text = value;
                    if (_parent != null)
                    {
                        _parent.Invalidate();
                    }
                }
            }

            public Rectangle Bounds
            {
                get => _bounds;
                set
                {
                    _bounds = value;
                    if (_parent != null)
                    {
                        _parent.Invalidate();
                    }
                }
            }

            public Control Parent
            {
                get => _parent;
                set
                {
                    if (_parent == value)
                    {
                        return;
                    }
                    if (_parent != null)
                    {
                        _parent.Paint -= Paint;
                        _parent.MouseMove -= MouseMove;
                        _parent.MouseDown -= MouseDown;
                        _parent.MouseUp -= MouseUp;
                        _parent.Invalidate();
                    }
                    _parent = value;
                    if (_parent != null)
                    {
                        _parent.Paint += Paint;
                        _parent.MouseMove += MouseMove;
                        _parent.MouseDown += MouseDown;
                        _parent.MouseUp += MouseUp;
                        _parent.Invalidate();
                    }
                }
            }

            private void MouseUp(object sender, MouseEventArgs e)
            {
                if ((_parent != null) && (e.Button == MouseButtons.Left) && (_down))
                {
                    _down = false;
                    _parent.Invalidate();
                }
            }

            private void MouseDown(object sender, MouseEventArgs e)
            {
                if ((_parent != null) && (e.Button == MouseButtons.Left) && (_hover) && (_down == false))
                {
                    _down = true;
                    _parent.Invalidate();
                }
            }

            private void MouseMove(object sender, MouseEventArgs e)
            {
                if (_parent == null)
                {
                    return;
                }
                var newHover = (_parent.RectangleToScreen(_bounds).Contains(MousePosition));
                if (_hover != newHover)
                {
                    _hover = newHover;
                    _down = false;
                    _parent.Invalidate();
                }
            }

            private void Paint(object sender, PaintEventArgs e)
            {
                if (_parent == null)
                {
                    return;
                }
                var src = new Rectangle(Point.Empty, _bounds.Size);
                using (var bitmap = new Bitmap(_bounds.Width, _bounds.Height, PixelFormat.Format32bppPArgb))
                {
                    using (var g = Graphics.FromImage(bitmap))
                    {
                        PushButtonState state;
                        if (_down)
                        {
                            state = PushButtonState.Pressed;
                        }
                        else if (_hover)
                        {
                            state = PushButtonState.Hot;
                        }
                        else
                        {
                            state = PushButtonState.Normal;
                        }
                        ButtonRenderer.DrawButton(g, src, state);
                        g.DrawString(_text, _parent.Font, SystemBrushes.ControlText, src
                            , new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
                    }
                    for (var y = 0; y < bitmap.Height; y++)
                    {
                        for (var x = 0; x < bitmap.Width; x++)
                        {
                            var c = bitmap.GetPixel(x, y);
                            bitmap.SetPixel(x, y, Color.FromArgb((int)(c.A * 0.7), c));
                        }
                    }
                    e.Graphics.DrawImage(bitmap, _bounds, src, GraphicsUnit.Pixel);
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            var c1 = new MyControl() { Text = "Control1", Bounds = new Rectangle(10, 10, 100, 35), Parent = this };
            var c2 = new MyControl() { Text = "Control2", Bounds = new Rectangle(50, 25, 100, 35), Parent = this };
            var c3 = new MyControl() { Text = "Control3", Bounds = new Rectangle(10, 50, 100, 35), Parent = this };
        }
    }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
تعجب کردم وقتی در مورد PictureBox گفتید. در خیلی از برنامه ها و حتی زبان های برنامه نویسی مثل Visual Basic 6 یک سری از کنترل ها از اساس بصورت بدون پنجره (Windowless) طراحی میشوند که اصولا کنترل های Focus پذیری نیستند، مگر اینکه خود محیط شون کلا کاری با کنترل های استاندارد ویندوز نداره و Focus رو شبیه سازی کرده باشه. مخصوصا برای برنامه هایی که تعداد کنترل گرافیکی زیادی دارند این کنترل های بدون پنجره بیشتر کاربرد داره. مشکل در شیشه ای کردن پنجره بود، وقتی پنجره ای در کار نباشه که دیگه صورت مساله حذف شده. کنترل های Windowless اصلا پنجره ای برای خودشون ندارند که حالا بخوان برای شیشه ای شدنش فکری کنند. به همین جهت به سادگی روی بخشی از پنجره زمینه شون رسم می شوند و برای شفاف بودنشون هم طبعا مشکلی نیست :
کد:
    using System.Windows.Forms.VisualStyles;
    using System.Drawing.Imaging;

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            DoubleBuffered = true;
        }

        private class MyControl
        {
            private Rectangle _bounds;
            private Control _parent;
            private bool _hover;
            private bool _down;
            private string _text;

            public string Text
            {
                get => _text;
                set
                {
                    _text = value;
                    if (_parent != null)
                    {
                        _parent.Invalidate();
                    }
                }
            }

            public Rectangle Bounds
            {
                get => _bounds;
                set
                {
                    _bounds = value;
                    if (_parent != null)
                    {
                        _parent.Invalidate();
                    }
                }
            }

            public Control Parent
            {
                get => _parent;
                set
                {
                    if (_parent == value)
                    {
                        return;
                    }
                    if (_parent != null)
                    {
                        _parent.Paint -= Paint;
                        _parent.MouseMove -= MouseMove;
                        _parent.MouseDown -= MouseDown;
                        _parent.MouseUp -= MouseUp;
                        _parent.Invalidate();
                    }
                    _parent = value;
                    if (_parent != null)
                    {
                        _parent.Paint += Paint;
                        _parent.MouseMove += MouseMove;
                        _parent.MouseDown += MouseDown;
                        _parent.MouseUp += MouseUp;
                        _parent.Invalidate();
                    }
                }
            }

            private void MouseUp(object sender, MouseEventArgs e)
            {
                if ((_parent != null) && (e.Button == MouseButtons.Left) && (_down))
                {
                    _down = false;
                    _parent.Invalidate();
                }
            }

            private void MouseDown(object sender, MouseEventArgs e)
            {
                if ((_parent != null) && (e.Button == MouseButtons.Left) && (_hover) && (_down == false))
                {
                    _down = true;
                    _parent.Invalidate();
                }
            }

            private void MouseMove(object sender, MouseEventArgs e)
            {
                if (_parent == null)
                {
                    return;
                }
                var newHover = (_parent.RectangleToScreen(_bounds).Contains(MousePosition));
                if (_hover != newHover)
                {
                    _hover = newHover;
                    _down = false;
                    _parent.Invalidate();
                }
            }

            private void Paint(object sender, PaintEventArgs e)
            {
                if (_parent == null)
                {
                    return;
                }
                var src = new Rectangle(Point.Empty, _bounds.Size);
                using (var bitmap = new Bitmap(_bounds.Width, _bounds.Height, PixelFormat.Format32bppPArgb))
                {
                    using (var g = Graphics.FromImage(bitmap))
                    {
                        PushButtonState state;
                        if (_down)
                        {
                            state = PushButtonState.Pressed;
                        }
                        else if (_hover)
                        {
                            state = PushButtonState.Hot;
                        }
                        else
                        {
                            state = PushButtonState.Normal;
                        }
                        ButtonRenderer.DrawButton(g, src, state);
                        g.DrawString(_text, _parent.Font, SystemBrushes.ControlText, src
                            , new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
                    }
                    for (var y = 0; y < bitmap.Height; y++)
                    {
                        for (var x = 0; x < bitmap.Width; x++)
                        {
                            var c = bitmap.GetPixel(x, y);
                            bitmap.SetPixel(x, y, Color.FromArgb((int)(c.A * 0.7), c));
                        }
                    }
                    e.Graphics.DrawImage(bitmap, _bounds, src, GraphicsUnit.Pixel);
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            var c1 = new MyControl() { Text = "Control1", Bounds = new Rectangle(10, 10, 100, 35), Parent = this };
            var c2 = new MyControl() { Text = "Control2", Bounds = new Rectangle(50, 25, 100, 35), Parent = this };
            var c3 = new MyControl() { Text = "Control3", Bounds = new Rectangle(10, 50, 100, 35), Parent = this };
        }
    }

خیلی ممنون استاد علی.
درباره ی تفاوت کنترل های windowsless و کنترل های با ویندوز ، چیزی نمیدونم .
اما میخوام مثلا یه کلاسی باشه تا ازش ارث ببرم تا مثلا برای رویدادهای کلیک و یا بعضی از پروپرتی ها و این چیزاش مشکلی نداشته باشم و خودم از اول ننویسم . خود ویژال بیسیک که میگفتین ، زبان هه . اون دات نت بود که از کلاس هاش استفاده میکردیم.
حالا کلا در ویژال بیسیک ، همچین کلاسی وجود نداره که ارث ببرم تا رسم را خودم انجام بدم؟
بعد اینکه من الان واسم جای تعجب هه . من الان توی اتوپلی ، یه دکمه (ی رنگی) میذارم و روی اون دکمه ، یه لیبل رو میذارم ، از جاهای خالی لیبل (جاهایی از لیبل که transparent هه) ، اون دکمه ی پشت اش مشخص هه. اما همین کار را توی سی شارپ میکنم ، دکمه ی پشت اش مشخص نیست و کل پشت زمینه ی لیبل ، رنگ آمیزی (با رنگ کنترل parent اش) داره. چرا؟ چون اتوپلی از اشیاء activex استفاده میکنه و در سی شارپ از اشیاء دات نت استفاده میشه؟ یعنی اشیاء دات نت ، این نوع کنترل ها را ساپورت نمیکنن؟ برای این کار در سی شارپ ، باید از کنترل های activex استفاده کنم؟

فوکوس و اینا برام مهم نیست . بیشتر برام مانور روی رسم مهم هه (رویداد و یا متد paint) و یه چند پروپرتی و رویداد و توابع مهم کاربردی کنترل ها (خیلی از اعضای و پروپرتی های کم اهمیت ، برام مهم نیست) . کلا این دکمه ها را بیشتر برای گزینه ی OK و Cancel میخوام.
خیلی ممنون که کد دادین اما کد لازم نیست زحمت بکشین . فقط راهنمایی کنین ، خودم کد رو مینویسم.
 
آخرین ویرایش:

the_king

مدیرکل انجمن
خیلی ممنون استاد علی.
درباره ی تفاوت کنترل های windowsless و کنترل های با ویندوز ، چیزی نمیدونم .

جستجو کنید، مثل تفاوت جانداران مهره داران و جانداران بی مهرگان ئه.
اما میخوام مثلا یه کلاسی باشه تا ازش ارث ببرم تا مثلا برای رویدادهای کلیک و یا بعضی از پروپرتی ها و این چیزاش مشکلی نداشته باشم و خودم از اول ننویسم . خود ویژال بیسیک که میگفتین ، زبان هه . اون دات نت بود که از کلاس هاش استفاده میکردیم.
حالا کلا در ویژال بیسیک ، همچین کلاسی وجود نداره که ارث ببرم تا رسم را خودم انجام بدم؟
ابدا. چیزی که بدرد NET. تون بخوره نداره، خودش هم در حد MMB منسوخ و قدیمی شده. وراثت هم در ویژوال بیسیک با اون چیزی که میشناسید متفاوته و کنترل هایی که پنجره ندارند وراثت پذیر نیستند، UserControl هاش وراثت دارند که اونم پنجره دارند. در ضمن کد نویسی یک کلاس Windowless راحت تر از وراثت از کلاسی ئه که از پلتفرم دیگری اومده. تنها کاری که می توانید بکنید گشتن در اینترنت برای کلاسی است که قبلا یک ساختار قابل قبول برای Windowless رو در NET. پیاده سازی کرده باشه که اونم شاید مناسبتون باشه و شاید نباشه. در ضمن کنترلی که رخدادی مثل کلیک کردنش از قبل مشخص شده باشه طبعا کار کنترلش هم محدود ئه.

بعد اینکه من الان واسم جای تعجب هه . من الان توی اتوپلی ، یه دکمه (ی رنگی) میذارم و روی اون دکمه ، یه لیبل رو میذارم ، از جاهای خالی لیبل (جاهایی از لیبل که transparent هه) ، اون دکمه ی پشت اش مشخص هه. اما همین کار را توی سی شارپ میکنم ، دکمه ی پشت اش مشخص نیست و کل پشت زمینه ی لیبل ، رنگ آمیزی (با رنگ کنترل parent اش) داره. چرا؟ چون اتوپلی از اشیاء activex استفاده میکنه و در سی شارپ از اشیاء دات نت استفاده میشه؟ یعنی اشیاء دات نت ، این نوع کنترل ها را ساپورت نمیکنن؟ برای این کار در سی شارپ ، باید از کنترل های activex استفاده کنم؟
هی دونه دونه مثال نزنید، گفتم که. اون دکمه های اتوپلی پنجره ندارند. در Visual Basic 6 هم Label ها پنجره ندارند، کنترلی که Focus نمیگیره ضرورتی برای پنجره داشتن نداره، مثل Label ها. خودتون می توانید با ماوس روی کنترل ها بگردید و بررسی کنید که کدوم کنترل ها پنجره دارند (کادر آبی)
کد:
    public partial class Form1 : Form
    {
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINTAPI
        {
            public int X;
            public int Y;
        }

        [DllImport("user32.dll")]
        private static extern int GetWindowRect(IntPtr hwnd, ref RECT lpRect);

        [DllImport("user32.dll")]
        private static extern IntPtr WindowFromPoint(POINTAPI point);

        Timer _timer1 = new Timer() { Interval = 100, Enabled = true };
        Form _leftBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _rightBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _topBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _bottomBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _timer1.Tick += Timer1_Tick;
        }

        private void Timer1_Tick(object sender, EventArgs e)
        {
            var pos = new POINTAPI() { X = MousePosition.X, Y = MousePosition.Y };
            var hwnd = WindowFromPoint(pos);
            var rect = new RECT();
            if (hwnd == IntPtr.Zero)
            {
                _leftBorder.Visible = false;
                _rightBorder.Visible = false;
                _topBorder.Visible = false;
                _bottomBorder.Visible = false;
                return;
            }
            GetWindowRect(hwnd, ref rect);
            _leftBorder.Bounds = new Rectangle(rect.Left - 2, rect.Top - 2, 2, rect.Bottom - rect.Top + 4);
            _leftBorder.Visible = true;
            _rightBorder.Bounds = new Rectangle(rect.Right, rect.Top - 2, 2, rect.Bottom - rect.Top + 4);
            _rightBorder.Visible = true;
            _topBorder.Bounds = new Rectangle(rect.Left, rect.Top - 2, rect.Right - rect.Left + 1, 2);
            _topBorder.Visible = true;
            _bottomBorder.Bounds = new Rectangle(rect.Left, rect.Bottom, rect.Right - rect.Left + 1, 2);
            _bottomBorder.Visible = true;
        }
    }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
جستجو کنید، مثل تفاوت جانداران مهره داران و جانداران بی مهرگان ئه.

ابدا. چیزی که بدرد NET. تون بخوره نداره، خودش هم در حد MMB منسوخ و قدیمی شده. وراثت هم در ویژوال بیسیک با اون چیزی که میشناسید متفاوته و کنترل هایی که پنجره ندارند وراثت پذیر نیستند، UserControl هاش وراثت دارند که اونم پنجره دارند. در ضمن کد نویسی یک کلاس Windowless راحت تر از وراثت از کلاسی ئه که از پلتفرم دیگری اومده. تنها کاری که می توانید بکنید گشتن در اینترنت برای کلاسی است که قبلا یک ساختار قابل قبول برای Windowless رو در NET. پیاده سازی کرده باشه که اونم شاید مناسبتون باشه و شاید نباشه. در ضمن کنترلی که رخدادی مثل کلیک کردنش از قبل مشخص شده باشه طبعا کار کنترلش هم محدود ئه.


هی دونه دونه مثال نزنید، گفتم که. اون دکمه های اتوپلی پنجره ندارند. در Visual Basic 6 هم Label ها پنجره ندارند، کنترلی که Focus نمیگیره ضرورتی برای پنجره داشتن نداره، مثل Label ها. خودتون می توانید با ماوس روی کنترل ها بگردید و بررسی کنید که کدوم کنترل ها پنجره دارند (کادر آبی)
کد:
    public partial class Form1 : Form
    {
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINTAPI
        {
            public int X;
            public int Y;
        }

        [DllImport("user32.dll")]
        private static extern int GetWindowRect(IntPtr hwnd, ref RECT lpRect);

        [DllImport("user32.dll")]
        private static extern IntPtr WindowFromPoint(POINTAPI point);

        Timer _timer1 = new Timer() { Interval = 100, Enabled = true };
        Form _leftBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _rightBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _topBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _bottomBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _timer1.Tick += Timer1_Tick;
        }

        private void Timer1_Tick(object sender, EventArgs e)
        {
            var pos = new POINTAPI() { X = MousePosition.X, Y = MousePosition.Y };
            var hwnd = WindowFromPoint(pos);
            var rect = new RECT();
            if (hwnd == IntPtr.Zero)
            {
                _leftBorder.Visible = false;
                _rightBorder.Visible = false;
                _topBorder.Visible = false;
                _bottomBorder.Visible = false;
                return;
            }
            GetWindowRect(hwnd, ref rect);
            _leftBorder.Bounds = new Rectangle(rect.Left - 2, rect.Top - 2, 2, rect.Bottom - rect.Top + 4);
            _leftBorder.Visible = true;
            _rightBorder.Bounds = new Rectangle(rect.Right, rect.Top - 2, 2, rect.Bottom - rect.Top + 4);
            _rightBorder.Visible = true;
            _topBorder.Bounds = new Rectangle(rect.Left, rect.Top - 2, rect.Right - rect.Left + 1, 2);
            _topBorder.Visible = true;
            _bottomBorder.Bounds = new Rectangle(rect.Left, rect.Bottom, rect.Right - rect.Left + 1, 2);
            _bottomBorder.Visible = true;
        }
    }

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
عجبی ها.
من وقتی opacity یک فرم را کم میکنم ، پشت زمینه ی فرم شفاف میشه اما وقتی فرم را فرزند فرم دیگه میکنم و opacity شو کم میکنم ، شفاف نمیشه!!
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
تعجب کردم وقتی در مورد PictureBox گفتید. در خیلی از برنامه ها و حتی زبان های برنامه نویسی مثل Visual Basic 6 یک سری از کنترل ها از اساس بصورت بدون پنجره (Windowless) طراحی میشوند که اصولا کنترل های Focus پذیری نیستند، مگر اینکه خود محیط شون کلا کاری با کنترل های استاندارد ویندوز نداره و Focus رو شبیه سازی کرده باشه. مخصوصا برای برنامه هایی که تعداد کنترل گرافیکی زیادی دارند این کنترل های بدون پنجره بیشتر کاربرد داره. مشکل در شیشه ای کردن پنجره بود، وقتی پنجره ای در کار نباشه که دیگه صورت مساله حذف شده. کنترل های Windowless اصلا پنجره ای برای خودشون ندارند که حالا بخوان برای شیشه ای شدنش فکری کنند. به همین جهت به سادگی روی بخشی از پنجره زمینه شون رسم می شوند و برای شفاف بودنشون هم طبعا مشکلی نیست :
کد:
    using System.Windows.Forms.VisualStyles;
    using System.Drawing.Imaging;

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            DoubleBuffered = true;
        }

        private class MyControl
        {
            private Rectangle _bounds;
            private Control _parent;
            private bool _hover;
            private bool _down;
            private string _text;

            public string Text
            {
                get => _text;
                set
                {
                    _text = value;
                    if (_parent != null)
                    {
                        _parent.Invalidate();
                    }
                }
            }

            public Rectangle Bounds
            {
                get => _bounds;
                set
                {
                    _bounds = value;
                    if (_parent != null)
                    {
                        _parent.Invalidate();
                    }
                }
            }

            public Control Parent
            {
                get => _parent;
                set
                {
                    if (_parent == value)
                    {
                        return;
                    }
                    if (_parent != null)
                    {
                        _parent.Paint -= Paint;
                        _parent.MouseMove -= MouseMove;
                        _parent.MouseDown -= MouseDown;
                        _parent.MouseUp -= MouseUp;
                        _parent.Invalidate();
                    }
                    _parent = value;
                    if (_parent != null)
                    {
                        _parent.Paint += Paint;
                        _parent.MouseMove += MouseMove;
                        _parent.MouseDown += MouseDown;
                        _parent.MouseUp += MouseUp;
                        _parent.Invalidate();
                    }
                }
            }

            private void MouseUp(object sender, MouseEventArgs e)
            {
                if ((_parent != null) && (e.Button == MouseButtons.Left) && (_down))
                {
                    _down = false;
                    _parent.Invalidate();
                }
            }

            private void MouseDown(object sender, MouseEventArgs e)
            {
                if ((_parent != null) && (e.Button == MouseButtons.Left) && (_hover) && (_down == false))
                {
                    _down = true;
                    _parent.Invalidate();
                }
            }

            private void MouseMove(object sender, MouseEventArgs e)
            {
                if (_parent == null)
                {
                    return;
                }
                var newHover = (_parent.RectangleToScreen(_bounds).Contains(MousePosition));
                if (_hover != newHover)
                {
                    _hover = newHover;
                    _down = false;
                    _parent.Invalidate();
                }
            }

            private void Paint(object sender, PaintEventArgs e)
            {
                if (_parent == null)
                {
                    return;
                }
                var src = new Rectangle(Point.Empty, _bounds.Size);
                using (var bitmap = new Bitmap(_bounds.Width, _bounds.Height, PixelFormat.Format32bppPArgb))
                {
                    using (var g = Graphics.FromImage(bitmap))
                    {
                        PushButtonState state;
                        if (_down)
                        {
                            state = PushButtonState.Pressed;
                        }
                        else if (_hover)
                        {
                            state = PushButtonState.Hot;
                        }
                        else
                        {
                            state = PushButtonState.Normal;
                        }
                        ButtonRenderer.DrawButton(g, src, state);
                        g.DrawString(_text, _parent.Font, SystemBrushes.ControlText, src
                            , new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
                    }
                    for (var y = 0; y < bitmap.Height; y++)
                    {
                        for (var x = 0; x < bitmap.Width; x++)
                        {
                            var c = bitmap.GetPixel(x, y);
                            bitmap.SetPixel(x, y, Color.FromArgb((int)(c.A * 0.7), c));
                        }
                    }
                    e.Graphics.DrawImage(bitmap, _bounds, src, GraphicsUnit.Pixel);
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            var c1 = new MyControl() { Text = "Control1", Bounds = new Rectangle(10, 10, 100, 35), Parent = this };
            var c2 = new MyControl() { Text = "Control2", Bounds = new Rectangle(50, 25, 100, 35), Parent = this };
            var c3 = new MyControl() { Text = "Control3", Bounds = new Rectangle(10, 50, 100, 35), Parent = this };
        }
    }

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

the_king

مدیرکل انجمن
خیلی ممنون
میگم چطوره بجای کنترل خاص ، از کنترل فرم در داخل کنترل کانتینر ها استفاده کنیم (بجای دکمه یا لیبل و ...) چون کنترل فرم ، ترنسپرنت میشه.
پنجره پنجره است، فرم هم پنجره است، کنترل هم پنجره است. هیچ تفاوت اساسی بین پنجره ها نیست. کلاسشون متفاوته ولی محدودیت پنجره ها سر جاشه.

عجبی ها.
من وقتی opacity یک فرم را کم میکنم ، پشت زمینه ی فرم شفاف میشه اما وقتی فرم را فرزند فرم دیگه میکنم و opacity شو کم میکنم ، شفاف نمیشه!!
لایه های نیمه شفاف از Windows 8 به بعد برای پنجره های فرزند هم پشتیبانی میشه، البته به شرطی که در Manifest پروژه تون مشخص کنید که به این پشتیبانی نیاز دارید.
با گزینه منو Project > Add New Item... > Application Manifest File
How to use WS_EX_LAYERED on child controls

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون
در اولین کد در صفحه ی زیر :
CreateParams Class (System.Windows.Forms)
وقتی پروپرتی CreateParams را بصورت زیر تغییر میدم :


کد:
        protected override CreateParams CreateParams
        {
            get
            {
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();

                // Extend the CreateParams property of the Button class.
                CreateParams cp = base.CreateParams;
                // Update the button Style.
                cp.Style |= 0x00000040; // BS_ICON value
                cp.ExStyle |= 0x00080000;

                return cp;
            }
        }

یعنی قسمت cp.ExStyle را اضافه میکنم ، موقع اضافه کردن این کنترل به فرم (زمان فراخونی متد this.Controls.Add) در کد زیر :


کد:
        private void FormTest_Shown(object sender, EventArgs e)
        {
            Icon icon = new Icon(@"E:\Software\Utility Software\Grapical Tools\Icon & Flash\icon\icon\ico\Evolution Icon 06.ico");
            MyIconButton myIconButton = new MyIconButton(icon);
            myIconButton.Bounds = new Rectangle(new Point(100, 175), new Size(150, 100));
            myIconButton.BackColor = Color.Red;

            this.Controls.Add(myIconButton);
            myIconButton.BringToFront();
        }

ارور میده که نمیتونه واسه ی این دکمه ، هندل ایجاد کنه. چرا؟
میخوام بجای اینکه از تابع SetWindowLongPtrA در ویندوز api برای تغییر شفافیت کنترل (با تغییر مقادیر Extended Window) استفاده کنم ، از توی خود دات نت این را کنترل و تغییر بدم برای شفافیت.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
جستجو کنید، مثل تفاوت جانداران مهره داران و جانداران بی مهرگان ئه.

ابدا. چیزی که بدرد NET. تون بخوره نداره، خودش هم در حد MMB منسوخ و قدیمی شده. وراثت هم در ویژوال بیسیک با اون چیزی که میشناسید متفاوته و کنترل هایی که پنجره ندارند وراثت پذیر نیستند، UserControl هاش وراثت دارند که اونم پنجره دارند. در ضمن کد نویسی یک کلاس Windowless راحت تر از وراثت از کلاسی ئه که از پلتفرم دیگری اومده. تنها کاری که می توانید بکنید گشتن در اینترنت برای کلاسی است که قبلا یک ساختار قابل قبول برای Windowless رو در NET. پیاده سازی کرده باشه که اونم شاید مناسبتون باشه و شاید نباشه. در ضمن کنترلی که رخدادی مثل کلیک کردنش از قبل مشخص شده باشه طبعا کار کنترلش هم محدود ئه.


هی دونه دونه مثال نزنید، گفتم که. اون دکمه های اتوپلی پنجره ندارند. در Visual Basic 6 هم Label ها پنجره ندارند، کنترلی که Focus نمیگیره ضرورتی برای پنجره داشتن نداره، مثل Label ها. خودتون می توانید با ماوس روی کنترل ها بگردید و بررسی کنید که کدوم کنترل ها پنجره دارند (کادر آبی)
کد:
    public partial class Form1 : Form
    {
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINTAPI
        {
            public int X;
            public int Y;
        }

        [DllImport("user32.dll")]
        private static extern int GetWindowRect(IntPtr hwnd, ref RECT lpRect);

        [DllImport("user32.dll")]
        private static extern IntPtr WindowFromPoint(POINTAPI point);

        Timer _timer1 = new Timer() { Interval = 100, Enabled = true };
        Form _leftBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _rightBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _topBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };
        Form _bottomBorder = new Form() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false, BackColor = Color.Blue, TopMost = true };

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _timer1.Tick += Timer1_Tick;
        }

        private void Timer1_Tick(object sender, EventArgs e)
        {
            var pos = new POINTAPI() { X = MousePosition.X, Y = MousePosition.Y };
            var hwnd = WindowFromPoint(pos);
            var rect = new RECT();
            if (hwnd == IntPtr.Zero)
            {
                _leftBorder.Visible = false;
                _rightBorder.Visible = false;
                _topBorder.Visible = false;
                _bottomBorder.Visible = false;
                return;
            }
            GetWindowRect(hwnd, ref rect);
            _leftBorder.Bounds = new Rectangle(rect.Left - 2, rect.Top - 2, 2, rect.Bottom - rect.Top + 4);
            _leftBorder.Visible = true;
            _rightBorder.Bounds = new Rectangle(rect.Right, rect.Top - 2, 2, rect.Bottom - rect.Top + 4);
            _rightBorder.Visible = true;
            _topBorder.Bounds = new Rectangle(rect.Left, rect.Top - 2, rect.Right - rect.Left + 1, 2);
            _topBorder.Visible = true;
            _bottomBorder.Bounds = new Rectangle(rect.Left, rect.Bottom, rect.Right - rect.Left + 1, 2);
            _bottomBorder.Visible = true;
        }
    }

ممنون استاد علی
بله اون کنترل های اتوپلی ، پنجره نداشتن (که شفاف میشدن) . آها واسه ی همینه که این نوع کنترل ها در اتوپلی ، هندل ندارن؟ مثلا نوع button و lable که در اتوپلی بدون پنجره هست هندل نداره اما نوع xButton که با پنجره هست ، هندل داره.
کنترل های بدون پنجره ، در واقع همون چیزی هستن که شما کد دادین؟ یعنی عملا کنترلی وجود نداره و صرفا رسم گرافیک در پنجره ی والد یا همون parent هست؟ در واقع اصلا چیزی جز رسم گرافیک نیستن و وجود خارجی به عنوان کنترل مجزا ندارن دیگه . درسته؟

من کد زیر را در سی شارپ ، در کلاس فرم نوشتم:

کد:
        [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetWindowLongPtrA")]
        private static extern long SetWindowLongPtrA(IntPtr hwnd, int nIndex, long dwNewLong);

        [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetLayeredWindowAttributes")]
        private static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);

        private int GWL_EXSTYLE = -20;
        private long WS_EX_LAYERED = 0x00080000;
        private uint LWA_ALPHA = 0x00000002, LWA_COLORKEY = 0x00000001;

        private void FormTest_Shown(object sender, EventArgs e)
        {
            Button btnTransparent = new Button();
            btnTransparent.Bounds = new Rectangle(new Point(50, 50), new Size(200, 100));
            btnTransparent.Text = "salam";
            btnTransparent.FlatStyle = FlatStyle.Flat;
            btnTransparent.BackColor = Color.Red;
            this.panel1.Controls.Add(btnTransparent);

            IntPtr hwnd = btnTransparent.Handle;
            FormTest.SetWindowLongPtrA(hwnd, this.GWL_EXSTYLE, this.WS_EX_LAYERED);
            FormTest.SetLayeredWindowAttributes(hwnd, 0, 50, this.LWA_ALPHA);
        }

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

the_king

مدیرکل انجمن
خیلی ممنون
در اولین کد در صفحه ی زیر :
CreateParams Class (System.Windows.Forms)
وقتی پروپرتی CreateParams را بصورت زیر تغییر میدم :


کد:
        protected override CreateParams CreateParams
        {
            get
            {
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();

                // Extend the CreateParams property of the Button class.
                CreateParams cp = base.CreateParams;
                // Update the button Style.
                cp.Style |= 0x00000040; // BS_ICON value
                cp.ExStyle |= 0x00080000;

                return cp;
            }
        }

یعنی قسمت cp.ExStyle را اضافه میکنم ، موقع اضافه کردن این کنترل به فرم (زمان فراخونی متد this.Controls.Add) در کد زیر :


کد:
        private void FormTest_Shown(object sender, EventArgs e)
        {
            Icon icon = new Icon(@"E:\Software\Utility Software\Grapical Tools\Icon & Flash\icon\icon\ico\Evolution Icon 06.ico");
            MyIconButton myIconButton = new MyIconButton(icon);
            myIconButton.Bounds = new Rectangle(new Point(100, 175), new Size(150, 100));
            myIconButton.BackColor = Color.Red;

            this.Controls.Add(myIconButton);
            myIconButton.BringToFront();
        }

ارور میده که نمیتونه واسه ی این دکمه ، هندل ایجاد کنه. چرا؟
میخوام بجای اینکه از تابع SetWindowLongPtrA در ویندوز api برای تغییر شفافیت کنترل (با تغییر مقادیر Extended Window) استفاده کنم ، از توی خود دات نت این را کنترل و تغییر بدم برای شفافیت.
مورد اول اینکه شما یک پنجره با CreateParams.ClassName مشخص و استاندارد کلاس BUTTON ایجاد می کنید که در نتیجه الزاما همه چیز به دلخواه شما انجام نخواهد شد.
مورد دوم اینکه من از این چند سطر کد نمی توانم نتیجه بگیرم که شما کدتون رو با Manifest ویرایش شده و در ویندوز های 8 به بعد دارید اجرا می کنید که همچنان این خطا رو دارید یا اصلا کاری با سازگاری WS_EX_LAYERED ندارید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
مورد اول اینکه شما یک پنجره با CreateParams.ClassName مشخص و استاندارد کلاس BUTTON ایجاد می کنید که در نتیجه الزاما همه چیز به دلخواه شما انجام نخواهد شد.
مورد دوم اینکه من از این چند سطر کد نمی توانم نتیجه بگیرم که شما کدتون رو با Manifest ویرایش شده و در ویندوز های 8 به بعد دارید اجرا می کنید که همچنان این خطا رو دارید یا اصلا کاری با سازگاری WS_EX_LAYERED ندارید.

ممنون
Manifest را دستکاری نکردم . توی اون کد هم که دادم ، چیزی نگفت.
جواب اون دو پست بالاتر (پست ۱۱۳۱) را هم میدین بی زحمت؟
الان دو راهکار کلی ، کلا وجود دار؟:
اول اینکه بجای ایجاد کنترل جدید ، فقط شکل مورد نظر را در گرافیک کنترل والد رسم کنیم و برای رویدادها و پروپرتی ها و کلا اعضا ، از اعضای خود کنترل والد کمک بگیریم برای اون به اصطلاح کنترل بدون پنجره ای که رسم میکنیم. تقریبا شبسه همون کدی که شما دادین.

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

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون
در اولین کد در صفحه ی زیر :
CreateParams Class (System.Windows.Forms)
وقتی پروپرتی CreateParams را بصورت زیر تغییر میدم :


کد:
        protected override CreateParams CreateParams
        {
            get
            {
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();

                // Extend the CreateParams property of the Button class.
                CreateParams cp = base.CreateParams;
                // Update the button Style.
                cp.Style |= 0x00000040; // BS_ICON value
                cp.ExStyle |= 0x00080000;

                return cp;
            }
        }

یعنی قسمت cp.ExStyle را اضافه میکنم ، موقع اضافه کردن این کنترل به فرم (زمان فراخونی متد this.Controls.Add) در کد زیر :


کد:
        private void FormTest_Shown(object sender, EventArgs e)
        {
            Icon icon = new Icon(@"E:\Software\Utility Software\Grapical Tools\Icon & Flash\icon\icon\ico\Evolution Icon 06.ico");
            MyIconButton myIconButton = new MyIconButton(icon);
            myIconButton.Bounds = new Rectangle(new Point(100, 175), new Size(150, 100));
            myIconButton.BackColor = Color.Red;

            this.Controls.Add(myIconButton);
            myIconButton.BringToFront();
        }

ارور میده که نمیتونه واسه ی این دکمه ، هندل ایجاد کنه. چرا؟
میخوام بجای اینکه از تابع SetWindowLongPtrA در ویندوز api برای تغییر شفافیت کنترل (با تغییر مقادیر Extended Window) استفاده کنم ، از توی خود دات نت این را کنترل و تغییر بدم برای شفافیت.

خیلی ممنون استاد علی . الحمد لله
مشکل را متوجه شدم.
در کد بالا (که نقل قول کردم) ، مقدار cp.ExStyle را باید برابر 0x20 میگرفتیم . یعنی برابر با مقدار WS_EX_TRANSPARENT .
من به هوای اینکه قبلا با تابع SetLayeredWindowAttributes و SetWindowLong کار میکردم ، فکر کردم اینجا هم باید اول مقدار WS_EX_LAYERED را ست کرد. اما نمیدونم با اون حال ، چرا کد بالا ارور داد . منیفست را هم دستکاری نکردم. بالاخره ، کد کلی ، این شد :


کد:
    class CustomControl : Control
    {
        private int WS_EX_TRANSPARENT = 0x20;
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams createParams = base.CreateParams;
                createParams.ExStyle |= WS_EX_TRANSPARENT;
                return createParams;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(new Pen(Brushes.Red, 4f), new Rectangle(2, 2, 350, 200));
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
        }
    }

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

the_king

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

جواب اون دو پست بالاتر (پست ۱۱۳۱) را هم میدین بی زحمت؟
بعضی مواردی که میگید اصلا فرض سوالش معنی نداره بشه پاسخی بهشون داد. اینکه بگید چون پنجره نداره پس عملا کنترلی وجود نداره بیمعنیه، جواب بله یا خیر نیست، سوالتون معنی نداره. کنترل بدون پنجره، پنجره نداره.
Windowless Controls - Windows applications
حالا چون پنجره نداره پس عملا کنترل نیست؟ کنترل بدون پنجره، یک گروه از کنترل ها است، از اسمش هم مشخصه که کنترل ئه، میتونه کد شناسایی منحصربفرد و کلاس (با class برنامه نویسی اشتباه گرفته نشه) و ابعاد و رنگ و فونت و ... هر مشخصه دیگری که کنترل های پنجره دار داره داشته باشه، فقط پنجره نداره. در مورد مجزا بودنش هم جای ابهامی نیست، c1 و c2 و c3 سه کنترل کاملا مجزا بودن، چطور می توانید تصور کنید که از هم تفکیک ناپذیر هستند، وقتی هر کدوم مشخصه های خودشون رو دارند با عکس العمل های مستقل، مثل گزینه های Toolbar، مثل اجزاء Scrollbar، مثل اجزاء منوی Start ویندوز.

در مورد مثالی هم که از اتوپلی زدید من تفاوتی در اجرا نمی بینم، البته من ویندوز 7 دارم و اصلا در این ویندوز نمیشه پنجره فرزندی نیمه شفاف باشه. هر شفافیتی هست از پنجره بالایی به فرزند ها میرسه.

الان دو راهکار کلی ، کلا وجود دار؟:
اول اینکه بجای ایجاد کنترل جدید ، فقط شکل مورد نظر را در گرافیک کنترل والد رسم کنیم و برای رویدادها و پروپرتی ها و کلا اعضا ، از اعضای خود کنترل والد کمک بگیریم برای اون به اصطلاح کنترل بدون پنجره ای که رسم میکنیم. تقریبا شبسه همون کدی که شما دادین.
اشتباه نکنید، شما که با پروپرتی های کنترل والد حداقل در روال کلی و برای این منظور کاری ندارید، مگر اینکه خودتون کار خاصی باهاشون داشته باشید که ربطی به این مساله نداره. کنترل بدون پنجره به یک پنجره نیاز ضروری داره، ولی نه مشخصه های کنترلی که حتی شاید نمیدونه قراره دقیقا از چه نوعی باشه. ثانیا شما با رویداد های کنترل والد کاری ندارید، با رویداد های پنجره والد کار دارید، این دو تا یک معنی ندارند. شاید کنترل والد اصلا رخدادی مثل Click نداشت، چون احتیاجی بهش نداره و برایش کاربردی نداره. اما کنترل بدون پنجره داخلش از رخداد کلیک پنجره والد استفاده کنه چون باید کلیک پذیر باشه و با کلیک کاری انجام بده.

دوم اینکه همون چیزی که گفتین یعنی یه کنترل واقعی و با پنجره ایجاد کنیم و از کنترل کنترل زیرش عکس و در اون کنترل مون رسن کنیم . اما برای آپدیت کردن رسم اش (تغییراتی که در رسم کنترل های زیرین اش اتفاق میافته) نیاز داریم تا یه لحظه ، اول کنترل مون را مخفی و بعد از فرم عکس بگیریم و بعد رسم را در کنترل مون به روز کنیم که این ، باعث سوسو زرن کنترل مون میشه.
از خودتون اسم اختراع نکنید. کنترل واقعی یعنی چی؟ شما جایی در منابع Real Control و Fake Control دیدید؟ اینکه شما پنجره رو یک لحظه مخفی کنید و از زیرش عکس بگیرید، یک راهکاری هست که به فکرتون میرسه، درست، Flicker یا سوسو زدن هم درست. ولی الزاما نیازی نیست که برای اجرای روش کلی دوم اینکار انجام بشه. اغلب پنجره ها در برابر پیام WM_PRINT پاسخ مناسب نشون میدن و که یکجور درخواست رسم ئه، ولی رسم در جای دلخواه مورد نظر فرستنده. یعنی میتوانند رسم شون رو در اون لحظه بجای اینکه در پنجره خودشون انجام بدن در DC گرافیکی مورد نظر فرستنده انجام بدن و نیازی هم به اینکه کنترل بالایی مخفی بشه نیست. اما همه پنجره ها و در هر شرایطی نمیتوانند با این پیام جور بشن و ثانیا اگر برای شفاف شدنشون راهکاری داشتند با این راهکار شما تداخل پیش میاد. اما اگر رسم کنترل های دیگه روی فرم رو هم خودتون مدیریت کرده باشید، مثل یک مجموعه کمپوننت که همگی با هم یکدست و هماهنگ هستند، اجرای این روش دوم خیلی ساده تر میشه، چون هم احتیاجی به WM_PRINT ندارید و هم میتوانید برای شفاف شدن چند کنترل روی هم یک راهکار مناسب داشته باشید.

همین دو راه وجود داره فقط دیگه؟ درسته؟
شما کدوم روش را پیشنهاد میدین؟ به نظر من همون روش اولی بهتره . درسته؟
ممنون
بله ولی در نظر بگیرید که اینها دو تا راهکار کلی ئه، نه جزئی و روش های مختلفی برای پیاده سازی دارند با جزئیات کاملا متفاوت.
من نمیتونم همینطور کلی براتون روشی رو پیشنهاد کنم، باید با توجه به نرم افزاری که دارید طراحی می کنید و نیازی که داره و زمان و هزینه ای که صرف اش میشه تصمیم بگیرید.
در پیاده سازی روش ها ریزه کاری ها خیلی متفاوت هستند. فرضا خیلی تفاوت هست بین کنترل های داخل Photoshop و Firefox و Adobe Flash و WPF و ...
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون
دوباره ، بی زحمت جواب پست بالایی (پست 1134) را میدین؟ چون جواب نهایی توی این پست هه .
ببخشیدا . خیلی ممنون. خدا اجرتون بده. :rose:
منم جواب پست بالا تون را بخونم.
 

the_king

مدیرکل انجمن
خیلی ممنون استاد علی . الحمد لله
مشکل را متوجه شدم.
در کد بالا (که نقل قول کردم) ، مقدار cp.ExStyle را باید برابر 0x20 میگرفتیم . یعنی برابر با مقدار WS_EX_TRANSPARENT .
من به هوای اینکه قبلا با تابع SetLayeredWindowAttributes و SetWindowLong کار میکردم ، فکر کردم اینجا هم باید اول مقدار WS_EX_LAYERED را ست کرد. اما نمیدونم با اون حال ، چرا کد بالا ارور داد . منیفست را هم دستکاری نکردم. بالاخره ، کد کلی ، این شد :


کد:
    class CustomControl : Control
    {
        private int WS_EX_TRANSPARENT = 0x20;
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams createParams = base.CreateParams;
                createParams.ExStyle |= WS_EX_TRANSPARENT;
                return createParams;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(new Pen(Brushes.Red, 4f), new Rectangle(2, 2, 350, 200));
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
        }
    }

اما فقط نمیدونم چرا مثلا یه کنترل دیگه ، زیرش میره و فوکوس روی اون کنترل زیرش انجام میشه (مثلا روش کلیک میشه) ، دیگه اون کنترل جلو میاد و شاید به عبارتی ، رسم این کنترل در اون ناحیه ، پاک میشه . نمیدونم با اونکه رویداد paint اش هم اجرا میشه ولی رسم را دوباره در اون ناحیه نمیکشه.
شاید باید متد Invalidate را فراخونی کرد ولی نمیدونم چه زمانی رسم پاک میشه. زمانی که فقط فوکوس روی کنترل زیرش بره؟ در رویداد فوکوس اون کنترل ها ، باید متد Invalidate این کنترل را فراخونی کرد؟
خیلی ممنون
WS_EX_TRANSPARENT راه حلی برای مشکل شما نیست. WS_EX_TRANSPARENT زمانی کاربرد داره که نیازی به لایه Alpha نداشته باشید و رسم ها مثل تصاویر GIF دندانه دندانه شدنشون مانعی نباشه. برای همینه که زیاد ازش استفاده نمیشه. کنترلی که WS_EX_TRANSPARENT ئه رسم شدنش یکم مشکل هماهنگی داره چون اول باید زیرش رسم بشه تا نوبت به رسمش برسه.
اون موردی هم که رخدادی توسط کنترل زیرین دریافت بشه و نشه به آزمون Hit Test بستگی داره که قراره بگه این نقطه در داخل پنجره هست یا نیست، پیام WM_NCHITTEST که اون WS_EX_TRANSPARENT رویش تاثیر میذاره. ارتباطی با Invalidate نداره چون اصلا دریافت کننده اون پنجره شناخته نشده.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
WS_EX_TRANSPARENT راه حلی برای مشکل شما نیست. WS_EX_TRANSPARENT زمانی کاربرد داره که نیازی به لایه Alpha نداشته باشید و رسم ها مثل تصاویر GIF دندانه دندانه شدنشون مانعی نباشه. برای همینه که زیاد ازش استفاده نمیشه. کنترلی که WS_EX_TRANSPARENT ئه رسم شدنش یکم مشکل هماهنگی داره چون اول باید زیرش رسم بشه تا نوبت به رسمش برسه.

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



اون موردی هم که رخدادی توسط کنترل زیرین دریافت بشه و نشه به آزمون Hit Test بستگی داره که قراره بگه این نقطه در داخل پنجره هست یا نیست، پیام WM_NCHITTEST که اون WS_EX_TRANSPARENT رویش تاثیر میذاره. ارتباطی با Invalidate نداره چون اصلا دریافت کننده اون پنجره شناخته نشده.

دقیقا متوجه ی منظورتون نشدم
منظورم اینه :

1.JPG

اون حاشیه ی قرمز داره ، شی کنترلی هه که من paint شو رسم کردم (ضلع سمت راست اش که نداره را در نظر نگیرید) . بعد از اینکه این کنترل را اضافه کردم ، بعدش به Front بقیه ی کنترل ها آوردم :

کد:
        private void Button12_Click(object sender, EventArgs e)
        {
            CustomControl customControl = new CustomControl();
            customControl.Bounds = new Rectangle(new Point(30, 70), new Size(150, 70));
            customControl.BackColor = Color.Red;

            this.panel1.Controls.Add(customControl);
            customControl.BringToFront();
}

اما باز هم به پشت کنترل (در اینجا به پشت کنترل progress) میره . چرا؟
 

SajjadKhati

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

SajjadKhati

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

کد:
        private void BtnPointer1_Click(object sender, EventArgs e)
        {
            unsafe
            {
                int number = 1444;
                int* pointer = &number;
                MessageBox.Show(((int)pointer).ToString());
                number = 95;
                pointer = &number;
                MessageBox.Show(((int)pointer).ToString());
            }
        }

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

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

بالا