C# 具有透明背景的透明图像问题

C# 具有透明背景的透明图像问题,c#,winforms,C#,Winforms,我在用透明背景显示透明图像时遇到问题。透明背景采用底层控件的颜色,这很好。。。但问题是,一些细节(线)的基础背景被覆盖的图像,可以看到在下面的图像。 这是我正在使用的代码。。。。这是注释的代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Media; using System.D

我在用透明背景显示透明图像时遇到问题。透明背景采用底层控件的颜色,这很好。。。但问题是,一些细节(线)的基础背景被覆盖的图像,可以看到在下面的图像。

这是我正在使用的代码。。。。这是注释的代码

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Media;
using System.Drawing;

namespace Simpe_Piano_new
{
    class MusicNote: PictureBox
    {
        public SoundPlayer sp = new SoundPlayer();
        Timer tmr = new Timer();
        public int pitch;        //The no. of the music key (e.g. the sound freuency).
        public int noteDuration; //Shape of note.
        public string noteShape;

        public MusicNote(int iPitch, int iNoteDuration)
            : base()
        {
            pitch = iPitch;
            noteDuration = iNoteDuration;
            Size = new Size(40, 40);
        }

        public void ShowNote()
        {   if (this.noteDuration == 1) noteShape = "Quaver.png"; 
            if (this.noteDuration == 4) noteShape = "Crotchet.png";
            if (this.noteDuration == 7) noteShape = "minim.png";
            if (this.noteDuration == 10) noteShape = "DotMin.png";
            if (this.noteDuration == 12) noteShape = "SemiBreve.png";
            this.BackgroundImage = Image.FromFile(noteShape);
            this.BackColor = Color.Transparent;
            Location = new Point((pitch * 40) - 40, 100);
        }
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
        }

        public void PlaySound()
        {
            sp.SoundLocation = this.pitch + ".wav";
            sp.Play();
        }

        public void StopSound()
        {
            sp.SoundLocation = this.pitch + ".wav";
            sp.Stop();
        }

        public void Play()
        {
            sp.SoundLocation = this.pitch + ".wav";
            sp.Play();
            //Time to play the duration
            tmr.Interval = noteDuration;
            tmr.Start();
            tmr.Tick += new System.EventHandler(ClockTick);
        }

        void ClockTick(object sender, EventArgs e)
        {
            sp.Stop();
            tmr.Stop();
        }


    }
}
这是底层控件的代码..music staff

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace Simpe_Piano_new
{
    public class MusicStaff: Panel
    {
        Pen myPen;
        Graphics g;

        public MusicStaff()
        {
            this.Size = new Size(1000, 150);
            this.Location = new Point(0, 0);
            this.BackColor = Color.Transparent;
            this.Paint += new PaintEventHandler(DrawLines);
        }

        private void DrawLines(object sender, PaintEventArgs pea)
        {
            myPen = new Pen(Color.Black, 1);
            g = this.CreateGraphics();
            for (int i = 1; i < 6; i++)
            {
                g.DrawLine(myPen, 0, (this.Height / 6) * i, this.Width, (this.Height / 6) * i);
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统图;
使用System.Windows.Forms;
名称空间Simpe_Piano_new
{
公开课音乐课:小组
{
我的笔;
图形g;
公共音乐事务
{
该尺寸=新尺寸(1000150);
该位置=新点(0,0);
this.BackColor=Color.Transparent;
this.Paint+=新的PaintEventHandler(绘制线);
}
专用作废抽绳(对象发送器、PaintEventArgs pea)
{
myPen=新笔(颜色:黑色,1);
g=this.CreateGraphics();
对于(int i=1;i<6;i++)
{
g、 抽绳(myPen,0,(this.Height/6)*i,this.Width,(this.Height/6)*i);
}
}
}
}
我发现C#不能很好地处理透明度。。。
任何帮助都将不胜感激

两个错误。PictureBox也支持透明图像,只要将其BackColor属性设置为Color.transparent即可。这是你为MusicStaff做的,但不是为MusicNote做的。分层透明不起作用,你不需要MusicStaff透明,只需要图片框

这种透明度是通过要求父对象将自身绘制到控件中以提供背景像素来模拟的。这是第二个错误,在DrawLines()方法中使用CreateGraphics()。它直接绘制到屏幕,而不是控制面。你必须在这里使用豌豆图形

请注意,使用PictureBox带来的附加值非常低。控件很昂贵,你很容易烧掉数百个控件来显示一张音乐。你会注意到,它会变得很慢。可以通过让MusicStaff使用Graphics自己绘制音符来避免这种情况。DrawImage()可以完成这项工作。透明度效果现在也简单多了,只不过是几层油漆而已。WPF就是这样做的。您需要处理的唯一不便是鼠标点击测试不再那么简单,您需要将面板的MouseDown事件的坐标映射到注释。只需保留一个列表,跟踪每个注释的显示位置。您将使用它进行绘制和鼠标点击测试。

在底层控件“MusicStaff”的子控件中添加顶部控件“MusicNote”

在初始化所有组件之后,类似这样的操作-

// mStaff: the MusicStaff object
// mNote: the MusicNote object
mStaff.Children.Add(mNote);
在旧场景中,表单是它们的父对象,因此它们在任何透明区域中显示表单背景

修改“MusicNote”的父项后,它会在透明区域显示“MusicStaff”背景


我希望这对你有帮助

您确定您的便笺图像是透明的吗?您还应该确保您的
MusicNote
父项
应该是面板
MusicStaff
,看起来像是您的表单,而不是您的面板。是的,我确信图像是透明的。。。我从另一个类调用这些方法,比如mn.ShowNote();表1.Ms.Controls.Add(mn);WARE mn是MusicNote的一个实例,Ms是MusicStaff的一个实例,因此我认为父项是MusicStaff。。。。