Прозрачные изображения с C# WinForms

Я работаю над приложением Windows Forms в VS 2008, и я хочу отображать одно изображение поверх другого, причем верхнее изображение представляет собой гифку или что-то с прозрачными частями.

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

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

Здесь дан ответ на повторяющийся вопрос (то же самое относится и к C#) - stackoverflow.com/questions/394426/…stackoverflow.com/questions/392257/…

user21826 28.12.2008 23:44

Ссылка на повторяющийся ответ не работает

Christian Gibbs 05.12.2019 05:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
24
2
51 737
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Поместите большой / нижний образ на PictureBox, затем добавьте обработчик события OnPaint и используйте одну из перегрузок e.Graphics.DrawImage(). Вы можете загрузить образ с помощью Image.FromFile().

Маленькое / верхнее изображение должно иметь альфа-канал и быть прозрачным на заднем плане, чтобы наложение работало. Вы легко сможете это сделать в Photoshop или чем-то подобном. Убедитесь, что вы сохраняете в формате, поддерживающем альфа-канал, например PNG.

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

Ответ принят как подходящий

Пару дней назад я был в похожей ситуации. Вы можете создать прозрачный элемент управления для размещения вашего изображения.

using System;
using System.Windows.Forms;
using System.Drawing;

public class TransparentControl : Control
{
    private readonly Timer refresher;
    private Image _image;

    public TransparentControl()
    {
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        BackColor = Color.Transparent;
        refresher = new Timer();
        refresher.Tick += TimerOnTick;
        refresher.Interval = 50;
        refresher.Enabled = true;
        refresher.Start();
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }

    protected override void OnMove(EventArgs e)
    {
        RecreateHandle();
    }


    protected override void OnPaint(PaintEventArgs e)
    {
        if (_image != null)
        {
            e.Graphics.DrawImage(_image, (Width / 2) - (_image.Width / 2), (Height / 2) - (_image.Height / 2));
        }
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
       //Do not paint background
    }

    //Hack
    public void Redraw()
    {
        RecreateHandle();
    }

    private void TimerOnTick(object source, EventArgs e)
    {
        RecreateHandle();
        refresher.Stop();
    }

    public Image Image
    {
        get
        {
            return _image;
        }
        set
        {
            _image = value;
            RecreateHandle();
        }
    }
}

Что за взлом? Я не вижу внутреннего вызова Redraw. Когда его нужно вызывать?

Greg Dean 28.02.2009 08:05

как видите, это Public. IIRC, я обнаружил ошибку при изменении размера закрепленного TransparentControl. Я думаю, что он исчезает из формы, поэтому я поставил этот метод Redraw для вызова из изменения размера формы.

Leon Tayson 01.03.2009 04:34

работает отлично. Единственная проблема, с которой я столкнулся, заключается в том, что, в отличие от PictureBox, я не мог настроить автоматическое изменение размера или растяжение. В остальном это работает как шарм. Спасибо, Леон!

GR7 24.02.2010 19:05

Для чего нужен таймер / обновление?

Cheeso 16.04.2010 01:05

Установите ControlFlags.ResizeRedraw.

SLaks 08.06.2010 23:37

Хак Redraw () был именно тем, что мне было нужно!

simon.d 26.01.2012 23:20

@Slaks Я думаю, вы имеете в виду: SetStyle (ControlStyles.ResizeRedraw, true);

BillW 05.02.2014 10:55

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

PandaWood 15.12.2014 06:23

Отлично! Но, к сожалению, когда элемент управления обновляется под изображением, он заставляет часть изображения, которая находится непосредственно над ним, исчезать (здесь речь идет об оси Z).

Hellon 27.11.2018 20:52

Обычно вы используете Invalidate () для перерисовки изображения. RecreateHandle () - это своего рода излишество.

Elmue 06.10.2020 21:47

PictureBox имеет 2 слоя изображений: BackgroundImage и Image, которые можно использовать независимо друг от друга, включая рисование и очистку.

Код vb.net (все кредиты Леону Тайсону):

Imports System
Imports System.Windows.Forms
Imports System.Drawing

Public Class TransparentControl
    Inherits Control

    Private ReadOnly Local_Timer As Timer
    Private Local_Image As Image

    Public Sub New()
        SetStyle(ControlStyles.SupportsTransparentBackColor, True)
        BackColor = Color.Transparent
        Local_Timer = New Timer
        With Local_Timer
            .Interval = 50
            .Enabled = True
            .Start()
        End With

        AddHandler Local_Timer.Tick, AddressOf TimerOnClick

    End Sub

    Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
        Get
            Dim cp As CreateParams
            cp = MyBase.CreateParams
            cp.ExStyle = &H20
            Return cp
        End Get
    End Property

    Protected Overrides Sub OnMove(ByVal e As System.EventArgs)
        MyBase.OnMove(e)
        RecreateHandle()
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        If Local_Image IsNot Nothing Then _
            e.Graphics.DrawImage(Local_Image, New Rectangle(0, 0, (Width / 2) - (Local_Image.Width / 2), (Height / 2) - (Local_Image.Height / 2)))

    End Sub

    Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
        ' DO NOT PAINT BACKGROUND
    End Sub

    ''' <summary>
    ''' Hack
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub ReDraw()
        RecreateHandle()
    End Sub

    Private Sub TimerOnClick(ByVal sender As Object, ByVal e As System.EventArgs)
        RecreateHandle()
        Local_Timer.Stop()

    End Sub

    Public Property Image As Image
        Get
            Return Local_Image
        End Get
        Set(ByVal value As Image)
            Local_Image = value
            RecreateHandle()
        End Set
    End Property
End Class

как я это использую?

RanJS 01.10.2019 20:39

Список похожих сообщений указан в конце этого ответа.

Этот ответ касается pictureBoxes и Winforms (в других сообщениях ниже некоторые повторяют, что WPF уже решает эту проблему)

  1. Создать Winform
  2. Создать x2 PictureBoxes
    • foreground_pictureBox // графическое окно перед 'фоном'
    • background_pictureBox // окно изображения "позади" переднего плана
  3. Добавьте событие 'paint' для каждого PictureBox
    • выбрать объект в «дизайнере»
    • выберите вкладку «Свойства» (или щелкните правой кнопкой мыши и выберите из всплывающего меню)
    • выберите кнопку событий (маленькая молния)
    • дважды щелкните пустое поле справа от события «краска»
  4. Добавьте следующий код в функцию загрузки основной формы (если она еще не добавлена, используйте подход из шага 3 и выберите «при загрузке», а не «рисовать»)

знак равно

private void cFeedback_Form_Load(object sender, EventArgs e)
{
    ...
    // Ensure that it is setup with transparent background
    foreground_pictureBox.BackColor = Color.Transparent;

    // Assign it's 'background'
    foreground_pictureBox.Parent = background_pictureBox;
    ...
}

5. В вызове paint для background_pictureBox:

знак равно

private void background_pictureBox_Paint(object sender, PaintEventArgs e)
{
    ...foreground_pictureBox_Paint(sender, e);
}

6. В вызове 'foreground_pictureBox_Paint' добавьте любые графические вызовы, которые вы хотите отображать на переднем плане.

Кажется, эта тема повторяется в нескольких постах:

как сделать изображение прозрачным

c-Sharp-Picturebox-прозрачный-фон-кажется-не-работает

сделать перекрытие Picturebox прозрачный в сети

проблема с картинками

Другие вопросы по теме