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





Поместите большой / нижний образ на 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. Когда его нужно вызывать?
как видите, это Public. IIRC, я обнаружил ошибку при изменении размера закрепленного TransparentControl. Я думаю, что он исчезает из формы, поэтому я поставил этот метод Redraw для вызова из изменения размера формы.
работает отлично. Единственная проблема, с которой я столкнулся, заключается в том, что, в отличие от PictureBox, я не мог настроить автоматическое изменение размера или растяжение. В остальном это работает как шарм. Спасибо, Леон!
Для чего нужен таймер / обновление?
Установите ControlFlags.ResizeRedraw.
Хак Redraw () был именно тем, что мне было нужно!
@Slaks Я думаю, вы имеете в виду: SetStyle (ControlStyles.ResizeRedraw, true);
Этот код TransparentControl был для меня катастрофой, он даже не рисовал изображение, которое я установил, он рисовал какую-то другую часть пользовательского интерфейса наугад. Вероятно, потому что мой пользовательский интерфейс скрыт во время перерисовки ... не уверен. Но непригоден для меня
Отлично! Но, к сожалению, когда элемент управления обновляется под изображением, он заставляет часть изображения, которая находится непосредственно над ним, исчезать (здесь речь идет об оси Z).
Обычно вы используете Invalidate () для перерисовки изображения. RecreateHandle () - это своего рода излишество.
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
как я это использую?
Список похожих сообщений указан в конце этого ответа.
Этот ответ касается pictureBoxes и Winforms (в других сообщениях ниже некоторые повторяют, что WPF уже решает эту проблему)
знак равно
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-прозрачный-фон-кажется-не-работает
Здесь дан ответ на повторяющийся вопрос (то же самое относится и к C#) - stackoverflow.com/questions/394426/…stackoverflow.com/questions/392257/…