C# 是否可以创建非形状控件?

C# 是否可以创建非形状控件?,c#,winforms,image,background,transparent,C#,Winforms,Image,Background,Transparent,我试图将一个没有确定形状的图像(例如帽子)放置在另一个图像控件的顶部。 问题是,由于控件有一个确定的形状,它保留默认的背景色以覆盖留空的空间。图像控件与图像的大小完全相同。 我尝试使用control.BackColor=Color.Transparent;但它似乎不起作用。 还有其他建议吗?您可以为此使用Control.Region GraphicsPath path = new GraphicsPath(); path.AddEllipse(control.ClientRectangle);

我试图将一个没有确定形状的图像(例如帽子)放置在另一个图像控件的顶部。 问题是,由于控件有一个确定的形状,它保留默认的背景色以覆盖留空的空间。图像控件与图像的大小完全相同。 我尝试使用control.BackColor=Color.Transparent;但它似乎不起作用。
还有其他建议吗?

您可以为此使用
Control.Region

GraphicsPath path = new GraphicsPath();
path.AddEllipse(control.ClientRectangle);
control.Region = new Region(path);
尝试此操作,您可以使用
GraphicsPath
创建任何形状,并将其设置为
Region
,例如,我创建了椭圆

编辑

如果只想设置BackColor=Color.Transparent。由于某些原因,某些控件不允许这样做。在这种情况下,您可以执行以下操作

public class CustomControl1 : Control
{
    public CustomControl1()
    {
        this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    }
}

创建控件的子代并设置
this.SetStyle(ControlStyles.SupportsTransparentBackColor,true)图片盒),则可以使用此技术将图像显示在彼此的顶部。图像应具有透明背景:

public class ImageControl : Control {
   public ImageControl(){
      SetStyle(ControlStyles.Opaque, true);
   }
   public Image Image {get;set;}
   protected override CreateParams CreateParams {
      get {
          CreateParams cp = base.CreateParams;
          cp.ExStyle |= 0x20;
          return cp;
      }
   }
   protected override void OnPaint(PaintEventArgs e){
      if(Image != null) e.Graphics.DrawImage(Image, Point.Empty);
   }
}
您可以使用上面的控件,而不是
PictureBox
。在运行时拖动此控件会导致闪烁。因此,如果您愿意,我认为只有一种解决方案使用
区域
。在这种方法中,您必须将
位图
转换为
区域
,并将该
区域
分配给
控件.Region
属性。
Chris Dunaway
提供的链接非常有助于您实现这一点。然而,我不得不说,
区域
的边界并不像您所期望的那样平滑。这就是这种方法的不足之处。为了您的方便,我将在这里发布稍加修改的代码,此代码使用
锁位
,其性能将优于原始代码:

public class Util {
//invert will toggle backColor to foreColor (in fact, I mean foreColor here is the Solid Color which makes your image distinct from the background).
    public static Region RegionFromBitmap(Bitmap bm, Color backColor, bool invert)
    {
        Region rgn = new Region();
        rgn.MakeEmpty();//This is very important            
        int argbBack = backColor.ToArgb();
        BitmapData data = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        int[] bits = new int[bm.Width * bm.Height];
        Marshal.Copy(data.Scan0, bits, 0, bits.Length);
        //
        Rectangle line = Rectangle.Empty;
        line.Height = 1;
        bool inImage = false;
        for (int i = 0; i < bm.Height; i++)
        {
            for (int j = 0; j < bm.Width; j++)
            {
                int c = bits[j + i * bm.Width];
                if (!inImage)
                {
                    if (invert ? c == argbBack : c != argbBack)
                    {
                        inImage = true;
                        line.X = j;
                        line.Y = i;
                    }
                }
                else if(invert ? c != argbBack : c == argbBack)
                {
                    inImage = false;
                    line.Width = j - line.X;
                    rgn.Union(line);
                }
            }
        }
        bm.UnlockBits(data);
        return rgn;
    }
}
//Use the code
//if your Bitmap is a PNG with transparent background, you can get the Region from it like this:
Region rgn = Util.RegionFromBitmap(yourPng, Color.FromArgb(0), false);
//if your Bitmap has a figure with solid color of Black, you can get the Region like this:
Region rgn = Util.RegionFromBitmap(yourPng, Color.Black, true);
公共类Util{
//反转将背景色切换为前景色(事实上,我的意思是前景色是使图像与背景不同的纯色)。
公共静态区域区域FromBitmap(位图bm、颜色背景色、布尔反转)
{
区域rgn=新区域();
rgn.MakeEmpty();//这非常重要
int argbBack=backColor.ToArgb();
BitmapData data=bm.LockBits(新矩形(0,0,bm.Width,bm.Height)、ImageLockMode.ReadOnly、PixelFormat.Format32bppArgb);
int[]位=新的int[bm.Width*bm.Height];
Marshal.Copy(data.Scan0,bit,0,bit.Length);
//
矩形线=矩形。为空;
直线高度=1;
bool-inImage=false;
对于(int i=0;i
图像本身是否透明?例如,PNG图像支持透明颜色。这对你的工作非常重要…编辑你的标题。请阅读:我相信这是WinForms,所以您可能希望在标记中指定它(而不是背景或图片框)。在注意到
BackColor
之前,我本来打算为WPF回答这个问题。是的,我的图像有一个PNG格式的透明背景。非传统形状可能会重复吗?如下图所示:如果该图像具有透明背景,则可以设置控件的
BackGroundImage
属性并设置Control.BackColor=Color.Transparent@SharonJDDorot-您可能会发现本文很有用: