TheRuudster Ответов: 3

Как сделать программно сгенерированные pictureboxes прозрачными друг для друга в VB.NET


Привет,

На прошлой неделе я опубликовал вопрос о том, чтобы сделать этикетки прозрачными друг для друга. Это прекрасно работало с меткой и самой формой, но потом я обнаружил, что сгенерированные метки все еще не прозрачны друг для друга.

После этого я решил попробовать то же самое с pictureboxes, потому что я думал, что они будут более совместимы с прозрачностью, к тому же легче манипулировать изображениями в pictureboxes, чем в ярлыках.

Но результат тот же, что и с метками, когда я генерирую pictureboxes через код, они не прозрачны друг для друга.

У кого-нибудь есть предложение исправить это?

Приветствия,
Руди

Что я уже пробовал:

Public Class TransparentPicturebox
        Inherits PictureBox

        Public Sub New()
            Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
            Me.BackColor = Color.Transparent
        End Sub

    End Class


Кроме того, изображения, которые я использовал, полностью прозрачны, иначе pictureboxes не были бы прозрачны для формы.

Maciej Los

Я где-то читал, что прозрачный элемент управления должен наследовать от Control (базовый класс для каждого элемента управления windows) вместо Label, PictureBox и т. д.

TheRuudster

Просто попробовал это сделать, но когда я наследую от control вместо picturebox, я не могу использовать свойства image и sizemode, которые мне нужны. Даже если я попытаюсь наследовать элемент управления, а затем использовать backgroundimage (для стандартного класса управления вместо image для pictureboxes), все равно не будет прозрачности, если два pictureboxes перекрываются. :(

3 Ответов

Рейтинг:
2

RickZeeland

Может быть, установка .родитель свойство picturebox поможет, смотрите: Прозрачные кнопки в .NET[^]


TheRuudster

да, я пробовал это сделать, но как бы вы это сделали, если бы элементы управления, которые должны быть прозрачны друг для друга, были равны?

RickZeeland

Я думаю, что вы всегда можете установить родителя, просто попробуйте это сделать :)

TheRuudster

но свойство .parent может быть установлено только для существующего элемента управления, не так ли? Поэтому я не думаю, что это вариант, потому что я создаю элементы управления во время выполнения.

RickZeeland

Сначала создайте оба элемента управления в коде, а затем установите свойство .parent одного из них в коде :)

TheRuudster


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim pic As New TransparentPicturebox With
{
.Visible = True,
.Size = New Drawing.Size(50, 50),
.SizeMode = PictureBoxSizeMode.StretchImage,
.BackColor = Color.Transparent,
.Image = ImageSelect(selection_id),
.Tag = selection_id
}

PictureBox1.Controls.Add(pic)

Dim picList As List(Of TransparentPicturebox) = New List(Of TransparentPicturebox)
For Each c As TransparentPicturebox In PictureBox1.Controls
If (TypeOf c Is TransparentPicturebox) Then
picList.Add(CType(c, TransparentPicturebox))
TextBox4.BackColor = Color.Red
End If

Next
picarray = picList.ToArray



TextBox1.Text = picnum
'picarray(lblnum).BackColor = Color.Red
If picnum > 0 Then
picarray(picnum).Parent = picarray(picnum - 1)
'picarray(lblnum).Parent = PictureBox1
End If



AddHandler pic.MouseDown, AddressOf PictureboxMouseDown
AddHandler pic.MouseMove, AddressOf PictureboxMouseMove
AddHandler pic.MouseUp, AddressOf PictureboxMouseUp
AddHandler pic.MouseWheel, AddressOf PictureboxMouseWheel
AddHandler pic.Click, AddressOf PictureboxMouseClick

TextBox3.Text = selection_id & ", " & picnum.ToString()

picnum = picnum + 1
End Sub


Теперь это мой тестовый код для того, чтобы сделать pictureboxes прозрачными друг для друга, и он вроде как работает. Проблема в том, что всякий раз, когда я добавляю picturebox, он появляется на родительском picturebox, и я больше не могу перемещать его во всей "области рисования" picturebox xD. Так я в принципе перенес .родительское свойство из области чертежа в другой созданный элемент управления PictureBox.

Есть ли способ установить оба этих элемента в качестве родительских для нового добавленного picturebox, чтобы вы могли переместить его в область рисования и сделать его прозрачным для других pictureboxes в области рисования одновременно?

RickZeeland

Может быть, вы можете использовать:
пикаррей(picnum).Родитель = picarray(0)

TheRuudster

Тот же результат...

RickZeeland

Или, может быть, использовать панель в качестве контейнера для ваших PictureBoxes ...

TheRuudster

ха-ха, да, я пробовал это еще до того, как начал работать с picturebox, но я изменил его на picturebox, потому что pictureboxes используют стандарт doublebuffer вместо того, чтобы включить его через код setstyle.

Рейтинг:
2

Maciej Los

Пожалуйста, прочтите мой комментарий к этому вопросу. Вот такая реализация TransparentLabel класс (который наследуется от Контроль[^]): Прозрачная Этикетка C# [^] (найдено на: Прозрачные этикетки в WinForms - Веб-журнал Рика Штрала[^])

Здесь есть еще одно решение: WinForms: как создать элемент управления, прозрачный для других элементов управления[^]


Рейтинг:
1

RickZeeland

Вот некоторый код, который использует Метод setstyle, это для пользовательской кнопки, но, возможно, ее можно адаптировать для PictureBox:

namespace PushButtonTransparent
{
    using System.Drawing;
    using System.Windows.Forms;
    using System;

    /// <summary>
    ///   Transparent Button with a normal and pressed state, preferably used with transparent .PNG images,
    ///   it can be used without images, in which case only a black rectangle is drawn.
    ///   The click event must be handled by the Form, and property <see cref="pressed"/> must be set.
    ///   This is an extended version of <see cref="PushButton"/> which supports:
    ///   - Transparancy
    ///   - Text
    ///   - Textcolor (ForeColor / <see cref="ForeColorPressed"/>)
    ///   - Font
    /// <example>
    /// <code>
    ///   PushButtonTransparent TransparentButton;
    ///   this.TransparentButton.Text = "Test button";
    ///   // Events, images and colors can be set in the designer, or in code:
    ///   this.TransparentButton.Click += this.ButtonClicked;
    ///   this.TransparentButton.MouseUp += this.PushButtonMouseUp;
    ///   // Set images:
    ///   this.TransparentButton.ImageNotPressed = Loader.LoadBitmap(ResourceId.show_manual);
    ///   this.TransparentButton.ImagePressed = Loader.LoadBitmap(ResourceId.show_manual_over);
    ///   this.TransparentButton.Pressed = true;
    /// </code>
    /// </example>
    /// </summary>
    public class PushButtonTransparent : Control  // , IButtonControl
    {
        private bool pressed;

        /// <summary>
        /// Initializes a new instance of the <see cref="PushButtonTransparent"/> class.
        /// </summary>
        public PushButtonTransparent()
        {
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.Opaque, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            ////this.BackColor = Color.Transparent;
        }

        /// <summary>
        /// Gets or sets imagePressed image.
        /// </summary>
        public Image ImagePressed { get; set; }

        /// <summary>
        /// Gets or sets ImageNotPressed image.
        /// </summary>
        public Image ImageNotPressed { get; set; }

        /// <summary>
        /// Gets or sets TextPosition, otherwise default position is calculated.
        /// </summary>
        public Point TextPosition { get; set; }

        /// <summary>
        /// Gets or sets TextAlignment: Near, Center, Far.
        /// Only if TextPosition is not set.
        /// </summary>
        public StringAlignment TextAlignment { get; set; }

        /// <summary>
        /// Gets or sets ForeColorPressed (text color when clicked).
        /// </summary>
        public Color ForeColorPressed { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether the button is pressed and forces a redraw.
        /// </summary>
        public bool Pressed
        {
            get
            {
                return this.pressed;
            }

            set
            {
                this.pressed = value;
                this.Invalidate();
            }
        }

        /// <summary>
        /// Gets CreateParams and sets WsExTransparent.
        /// </summary>
        protected override CreateParams CreateParams
        {
            get
            {
                const int WsExTransparent = 0x20;
                var cp = base.CreateParams;
                cp.ExStyle |= WsExTransparent;
                return cp;
            }
        }

        /// <summary>
        /// Draw ImageNotPressed / ImagePressed if property set.
        /// Draw a black rectangle if image is missing.
        /// Draw Text if property is set.
        /// </summary>
        /// <param name="pevent">
        /// The PaintEventArgs.
        /// </param>
        protected override void OnPaint(PaintEventArgs pevent)
        {
            Image buttonImage;
            var g = pevent.Graphics;
            int width;
            int height;
            SolidBrush textBrush;

            // this.Font = SkinSettings.FontDefault;
            // float scaleFactor = this.Font.Size / 8;

            if (this.pressed)
            {
                buttonImage = this.ImagePressed;
            }
            else
            {
                buttonImage = this.ImageNotPressed;
            }

            if (buttonImage == null)
            {
                // Draw a black rectangle if image is missing.
                width = Convert.ToInt32(this.ClientRectangle.Width * scaleFactor);
                height = Convert.ToInt32(this.ClientRectangle.Height * scaleFactor);
                g.DrawRectangle(Pens.Black, 0, 0, width - 1, height - 1);
            }
            else
            {
                // Sets the images' size and position
                width =  Convert.ToInt32(buttonImage.Size.Width * scaleFactor);
                height = Convert.ToInt32(buttonImage.Size.Height * scaleFactor);
                var rect = new Rectangle(0, 0, width, height); 
                //// Draw the image
                g.DrawImage(buttonImage, rect);

                //// Draw with Gamma correction.
                //var rect = new Rectangle(0, 0, width, height);
                //var imageAttr = new System.Drawing.Imaging.ImageAttributes();
                //imageAttr.SetGamma(2.0F);
                //g.DrawImage(buttonImage, rect, 0, 0, width, height, GraphicsUnit.Pixel, imageAttr);
            }

            // No text ? then return
            if (string.IsNullOrEmpty(this.Text))
            {
                return;
            }

            // Set the text font and style and draw it.
            if (this.pressed && !this.ForeColorPressed.IsEmpty)
            {
                // Pressed color.
                textBrush = new SolidBrush(this.ForeColorPressed);
            }
            else
            {
                // Normal color.
                textBrush = new SolidBrush(this.ForeColor);
            }

            // Draw the text on TextPosition if specified.
            if (!this.TextPosition.IsEmpty)
            {
                float x = this.TextPosition.X * scaleFactor;
                float y = this.TextPosition.Y * scaleFactor;
                g.DrawString(this.Text, this.Font, textBrush, x, y);
            }
            else
            {
                // Otherwise use TextAlignment.
                width = Convert.ToInt32(this.Width * scaleFactor);
                height = Convert.ToInt32(this.Height * scaleFactor);
                var rectF = new RectangleF(0F, (height / 2) - (this.Font.Height / 2), width, height);
                var strFormat = new StringFormat();
                strFormat.Alignment = this.TextAlignment;
                g.DrawString(this.Text, this.Font, textBrush, rectF, strFormat);
            }
        }

        /// <summary>
        /// OnPaintBackground must not be called.
        /// </summary>
        /// <param name="pevent">
        /// The PaintEventArgs.
        /// </param>
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            //// don't call the base class
            ////base.OnPaintBackground(pevent);
        }
    }
}