2013-07-16 3 views
0

Я пытаюсь разместить изображение, которое не имеет окончательной формы (например, шляпы) поверх другого элемента управления изображением. Дело в том, что, поскольку элемент управления имеет определенную форму, он оставляет цвет фона по умолчанию, чтобы закрыть пробел, оставленный пустым. Управление изображением - это тот же размер изображения. Я пробовал использовать control.BackColor = Color.Transparent; но он, похоже, не работает. Любые другие предложения?Возможно ли создать неформовое управление?

+2

ли само изображение прозрачное? Например, изображения PNG поддерживают прозрачный цвет. Это очень важно для вашей попытки работать ... –

+0

Отредактировано ваше название. Пожалуйста, прочтите следующее: http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles – RahulD

+0

Я считаю, что это WinForms, поэтому вы можете указать это в своих тегах (вместо этого фона или изображения). Я изначально собирался ответить на это для WPF, прежде чем отметить «BackColor». –

ответ

1

Вы можете использовать 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);, который должен сделать трюк

+0

Как насчет нетрадиционных форм ? Как этот: http://img2-2.timeinc.net/people/i/2013/pets/news/130218/cat-monopoly-600.jpg –

+0

Если на этом изображении есть Прозрачный фон, вы можете установить 'BackGroundImage' вашего Control Свойство и Set Control.BackColor = Color.Transparent; –

+0

Почему Color.Transparent не работает для вас, что происходит? –

0

Если ваш Image Control (подобно PictureBox) не перемещаются (удерживая мышь вниз и перетаскивание) пользователем во время выполнения, вы можете использовать эту технику, которая позволяет отображать изображения друг над другом. Изображения должны иметь прозрачный фон:

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. Перемещение этого элемента управления путем перетаскивания во время выполнения сильно мерцает. Поэтому, если вы так хотите, я думаю, что есть только 1 решение, которое использует Region. В этом подходе вам необходимо превратить Bitmap в Region и назначить Region для вашего Control.Region. Ссылка, предоставленная Chris Dunaway, очень полезна для вас. Однако я должен сказать, что Region не имеет гладкой границы, как вы можете ожидать. Это недостаток такого подхода. Для вашего удобства я выложу код с небольшой модификацией здесь, этот код использует LockBits, который будет опережать исходный код:

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); 
Смежные вопросы