私のプロジェクトでは、透明な背景で表示する画像が必要です。背景が透明な.png画像をいくつか作成しました(これを確認するために、Photoshopで開きました)。これで、PictureBoxを拡張するクラスができました。
class Foo : PictureBox
{
public Foo(int argument)
: base()
{
Console.WriteLine(argument);//different in the real application of course.
//MyProject.Properties.Resources.TRANSPARENCYTEST.MakeTransparent(MyProject.Properties.Resources.TRANSPARENCYTEST.GetPixel(1,1)); //<-- also tried this
this.Image = MyProject.Properties.Resources.TRANSPARENCYTEST;
((Bitmap)this.Image).MakeTransparent(((Bitmap)this.Image).GetPixel(1, 1));
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.BackColor = System.Drawing.Color.Transparent;
}
}
ただし、これは白い背景のピクチャボックスを表示するだけで、透明な背景で動作するようには思えません。
おそらく完全に機能します。ピクチャボックスコントロールの背後にあるものを見ています。それがフォームです。 BackColorはおそらく白です。フォームのBackgroundImageプロパティを設定して、画像が画像ボックスに表示されることを確認できます。このような:
bothピクチャーボックスおよびに穴を開けるには、フォームに大きな武器Form.TransparencyKeyが必要です
画像上に画像をオーバーレイしたい場合(フォーム上の画像ではなく)、これはトリックになります:
overImage.Parent = backImage;
overImage.BackColor = Color.Transparent;
overImage.Location = thePointRelativeToTheBackImage;
OverImageとbackImageは、png(透明な背景)を持つPictureBoxです。
これは、前述のように、親コンテナの背景色を使用して画像の透明度がレンダリングされるためです。 PictureBoxには「親」プロパティがないため、手動で作成する必要があります(またはもちろん、カスタムコントロールを作成する必要があります)。
CodeProject Webサイトの優れたソリューションがあります。
基本的には、paintboxイベントをオーバーライドして、pictureboxの基になるすべてのコントロールをループし、それらを再描画するのがコツです。機能は次のとおりです。
protected override void OnPaintBackground(PaintEventArgs e)
// Paint background with underlying graphics from other controls
{
base.OnPaintBackground(e);
Graphics g = e.Graphics;
if (Parent != null)
{
// Take each control in turn
int index = Parent.Controls.GetChildIndex(this);
for (int i = Parent.Controls.Count - 1; i > index; i--)
{
Control c = Parent.Controls[i];
// Check it's visible and overlaps this control
if (c.Bounds.IntersectsWith(Bounds) && c.Visible)
{
// Load appearance of underlying control and redraw it on this background
Bitmap bmp = new Bitmap(c.Width, c.Height, g);
c.DrawToBitmap(bmp, c.ClientRectangle);
g.TranslateTransform(c.Left - Left, c.Top - Top);
g.DrawImageUnscaled(bmp, Point.Empty);
g.TranslateTransform(Left - c.Left, Top - c.Top);
bmp.Dispose();
}
}
}
}
あなたの質問はC#にありますが、類似性とVB.NETからの変換の容易さのため、完全な[〜 #〜] vb [〜#〜]バージョンを移動すると、コントロールの背景も更新できます。
あなたはすでに答えを持っていますが、これは検索エンジンでこの投稿を見つけ、[〜#〜] vb [〜#〜]バージョンを希望するか、単にFULLを探したい人向けです。 C#で変換可能なサンプルも必要な場合.
新しいカスタムコントロールクラスを作成し、それに以下を貼り付けます...デフォルトクラスのものを上書きします。
カスタムコントロールクラス:
Public Class TransparentPictureBox
Private WithEvents refresher As Timer
Private _image As Image = Nothing
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
refresher = New Timer()
'refresher.Tick += New EventHandler(AddressOf Me.TimerOnTick)
refresher.Interval = 50
refresher.Start()
End Sub
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H20
Return cp
End Get
End Property
Protected Overrides Sub OnMove(ByVal e As EventArgs)
MyBase.OnMove(e)
MyBase.RecreateHandle()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
'Add your custom Paint code here
If _image IsNot Nothing Then
e.Graphics.DrawImage(_image, CInt(Width / 2) - CInt(_image.Width / 2), CInt(Height / 2) - CInt(_image.Height / 2))
End If
End Sub
Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
' Paint background with underlying graphics from other controls
MyBase.OnPaintBackground(e)
Dim g As Graphics = e.Graphics
If Parent IsNot Nothing Then
' Take each control in turn
Dim index As Integer = Parent.Controls.GetChildIndex(Me)
For i As Integer = Parent.Controls.Count - 1 To index + 1 Step -1
Dim c As Control = Parent.Controls(i)
' Check it's visible and overlaps this control
If c.Bounds.IntersectsWith(Bounds) AndAlso c.Visible Then
' Load appearance of underlying control and redraw it on this background
Dim bmp As New Bitmap(c.Width, c.Height, g)
c.DrawToBitmap(bmp, c.ClientRectangle)
g.TranslateTransform(c.Left - Left, c.Top - Top)
g.DrawImageUnscaled(bmp, Point.Empty)
g.TranslateTransform(Left - c.Left, Top - c.Top)
bmp.Dispose()
End If
Next
End If
End Sub
Public Property Image() As Image
Get
Return _image
End Get
Set(value As Image)
_image = value
MyBase.RecreateHandle()
End Set
End Property
Private Sub refresher_Tick(sender As Object, e As System.EventArgs) Handles refresher.Tick
MyBase.RecreateHandle()
refresher.Stop()
End Sub
End Class
...クラスを保存し、プロジェクトをクリーンアップして、再度ビルドします。新しいコントロールは、新しいツールアイテムとして表示されます。それを見つけて、フォームにドラッグします。
ただし、このコントロールに問題があります...アニメーションの「読み込み中」。gif画像を読み込もうとすると発生します。
画像はアニメーション化されず、コントロールを非表示にしてからもう一度表示しようとすると表示上の問題が発生します。
これらの問題を整理すると、完璧なカスタムコントロールクラスが得られます。 :)
編集:
以下がC# 's IDE=かどうかで動作するかどうかはわかりませんが、変換の試みは次のとおりです。
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class TransparentPictureBox
{
private Timer withEventsField_refresher;
private Timer refresher {
get { return withEventsField_refresher; }
set {
if (withEventsField_refresher != null) {
withEventsField_refresher.Tick -= refresher_Tick;
}
withEventsField_refresher = value;
if (withEventsField_refresher != null) {
withEventsField_refresher.Tick += refresher_Tick;
}
}
}
private Image _image = null;
public TransparentPictureBox()
{
// This call is required by the designer.
InitializeComponent();
// Add any initialization after the InitializeComponent() call.
refresher = new Timer();
//refresher.Tick += New EventHandler(AddressOf Me.TimerOnTick)
refresher.Interval = 50;
refresher.Start();
}
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | 0x20;
return cp;
}
}
protected override void OnMove(EventArgs e)
{
base.OnMove(e);
base.RecreateHandle();
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
base.OnPaint(e);
//Add your custom Paint code here
if (_image != null) {
e.Graphics.DrawImage(_image, Convert.ToInt32(Width / 2) - Convert.ToInt32(_image.Width / 2), Convert.ToInt32(Height / 2) - Convert.ToInt32(_image.Height / 2));
}
}
protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)
{
// Paint background with underlying graphics from other controls
base.OnPaintBackground(e);
Graphics g = e.Graphics;
if (Parent != null) {
// Take each control in turn
int index = Parent.Controls.GetChildIndex(this);
for (int i = Parent.Controls.Count - 1; i >= index + 1; i += -1) {
Control c = Parent.Controls(i);
// Check it's visible and overlaps this control
if (c.Bounds.IntersectsWith(Bounds) && c.Visible) {
// Load appearance of underlying control and redraw it on this background
Bitmap bmp = new Bitmap(c.Width, c.Height, g);
c.DrawToBitmap(bmp, c.ClientRectangle);
g.TranslateTransform(c.Left - Left, c.Top - Top);
g.DrawImageUnscaled(bmp, Point.Empty);
g.TranslateTransform(Left - c.Left, Top - c.Top);
bmp.Dispose();
}
}
}
}
public Image Image {
get { return _image; }
set {
_image = value;
base.RecreateHandle();
}
}
private void refresher_Tick(object sender, System.EventArgs e)
{
base.RecreateHandle();
refresher.Stop();
}
}
試してみて、自分で確かめてみてください:P
ps:私は第一人者ではないので、C#とVB.NETの両方のバージョンであらゆる種類の間違いを期待しています。笑
画像ボックスに透過表示のpngを表示している場合、透過表示が自動的に考慮されるため、透過色を設定する必要はありません。
上記の答えはあなたの問題を解決するようです。実際、ピクチャボックスコントロールの背後にあるもの-backColorが白のフォーム自体が表示されています。ここでは、最初にバイトタイプ(配列)のイメージをビットマップに変換し、その後特定の色(ビットマップpicから)を透明に設定する単純な関数を作成しました。使用する可能性のあるもの:
using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms;
public void LogoDrawTransparent(PaintEventArgs e)
{
// Create a Bitmap object from an image file.
Image myImg;
Bitmap myBitmap;
try
{
myImg = cls_convertImagesByte.GetImageFromByte(newImg);
myBitmap = new Bitmap(myImg); // @"C:\Temp\imgSwacaa.jpg");
// Get the color of a background pixel.
Color backColor = myBitmap.GetPixel(0, 0); // GetPixel(1, 1);
Color backColorGray = Color.Gray;
Color backColorGrayLight = Color.LightGray;
Color backColorWhiteSmoke = Color.WhiteSmoke;
Color backColorWhite = Color.White;
Color backColorWheat = Color.Wheat;
// Make backColor transparent for myBitmap.
myBitmap.MakeTransparent(backColor);
// OPTIONALLY, you may make any other "suspicious" back color transparent (usually gray, light gray or whitesmoke)
myBitmap.MakeTransparent(backColorGray);
myBitmap.MakeTransparent(backColorGrayLight);
myBitmap.MakeTransparent(backColorWhiteSmoke);
// Draw myBitmap to the screen.
e.Graphics.DrawImage(myBitmap, 0, 0, pictureBox1.Width, pictureBox1.Height); //myBitmap.Width, myBitmap.Height);
}
catch
{
try { pictureBox1.Image = cls_convertImagesByte.GetImageFromByte(newImg); }
catch { } //must do something
}
}
このファンクをpictureBoxのペイントで起動できます。これは、上記の関数で参照される私のクラスです:
class cls_convertImagesByte
{
public static Image GetImageFromByte(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
public static byte[] GetByteArrayFromImage(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
}
ありがとう。シャグバート