2012-06-30 152 views
7

我一直在試圖顯示一個具有透明邊框作爲控件背景的圖像。帶透明背景的繪圖控制

不幸的是,透明的區域會在父表孔如下:

在上圖中,形式有哪些我所希望看到我在背後控制紅色背景透明區域。

我使用的代碼如下:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
    { 
     if (this.Image != null) 
     { 
      Graphics g = Graphics.FromImage(this.Image); 

      ImageAttributes attr = new ImageAttributes(); 

      //set the transparency based on the top left pixel 
      attr.SetColorKey((this.Image as Bitmap).GetPixel(0, 0), (this.Image as Bitmap).GetPixel(0, 0)); 

      //draw the image using the image attributes. 
      Rectangle dstRect = new Rectangle(0, 0, this.Image.Width, this.Image.Height); 

      e.Graphics.DrawImage(this.Image, dstRect, 0, 0, this.Image.Width, this.Image.Height, 
       GraphicsUnit.Pixel, attr); 
     } 
     else 
     { 
      base.OnPaint(e); 
     } 
    } 

    protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e) 
    { 
     //base.OnPaintBackground(e); 
    } 

這類是從一個PictureBox繼承因爲我需要它實現的OnMouseMove和OnMouseUp活動的控制。

我一直在研究大部分時間沒有成功測試出不同的想法,但不幸的是,大多數只能在完整的框架上工作,而不是.Net CF.

任何想法將不勝感激。

回答

6

啊,CF透明度的樂趣。我可以繼續談論它(並有in my blogProject Resistance code我很久以前做過)。

的要點是這樣的。子控件必須繪製它的區域,但首先必須回調它的父項(在您的案例中爲Form),並告訴它在除了子項的裁剪區域之外的任何地方都重繪它的背景圖像,然後繪製它自己的頂部。如果這聽起來有點混亂,那是因爲它。

例如,如果你看Project Resistance,View(它只是一個Control)繪製一個電阻和帶。它坐落在具有圖像背景形式,以及背景需要「透視」電阻的透明區域:

enter image description here

所以它這樣做電阻的繪製代碼:

protected override void OnPaint(PaintEventArgs e) 
{ 
    base.OnPaint(e); 

    try 
    { 
     RECT rect = new RECT(this.Bounds); 

     // draw the blank 
     Infrastructure.GraphicTools.DrawTransparentBitmap(e.Graphics, m_blankImage, Bounds, 
       new Rectangle(0, 0, m_blankImage.Width, m_blankImage.Height)); 

     if (m_bandsImage != null) 
     { 
      // draw the bands 
      Infrastructure.GraphicTools.DrawTransparentBitmap(e.Graphics, m_bandsImage, Bounds, 
       new Rectangle(0, 0, m_bandsImage.Width, m_bandsImage.Height)); 
     } 
    } 
    finally 
    { 
    } 

    if (!Controller.TouchMode) 
    { 
     // TODO: draw in the selection arrow 
     // Controller.SelectedBand 
    } 
} 

這很簡單。最關鍵的是,它調用它的基本的OnPaint,這將會:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
{ 
    // this assumes we're in a workspace, on MainForm (the whole Parent.Parent thing) 
    IBackgroundPaintProvider bgPaintProvider = Parent.Parent as IBackgroundPaintProvider; 
    if (bgPaintProvider != null) 
    { 
     Rectangle rcPaint = e.ClipRectangle; 
     // use the parent, since it's the workspace position in the Form we want, 
     // not our position in the workspace 
     rcPaint.Offset(Parent.Left, Parent.Top); 
     bgPaintProvider.PaintBackground(e.Graphics, e.ClipRectangle, rcPaint); 
    } 
} 

你可以看到它調用了含有形式的PaintBackground(這是Parent.Parent在這種情況下becuse的控制實際上是一個容器稱爲工作區 - 你不需要在你的案例中走兩次)。這在你目前看到的作爲「洞」的區域繪製背景圖像

public void PaintBackground(Graphics g, Rectangle targetRect, Rectangle sourceRect) 
{ 
    g.DrawImage(m_bmBuffer, targetRect, sourceRect, GraphicsUnit.Pixel); 
} 
+0

哇,謝謝你。一個非常有用和詳細的解釋。你肯定花了一些時間在這個問題上。 –

+0

@ctacke我想出了一個非常接近你的透明度解決方案,它可以在設計器和運行時使用。我最近意識到我的解決方案在嵌套容器控件時不起作用,因爲「Parent.Parent」不起作用。我嘗試將「Parent.Parent」切換到this.TopLevelControl,它在運行時工作,但不是在設計時。在哪裏你可以得到一個解決方案來在Container控件中嵌套透明控件,並且仍然讓設計者使控件變得透明? –

+0

幾年前,我放棄了甚至試圖爲我的控件獲得設計師支持。它從來沒有覺得這對我很重要,而且總是很脆弱。有時候它會起作用,其他時候它不會,我發現自己燃燒了幾天,實際上沒有做出什麼高效率的事情,所以我甚至從來沒有打算控制設計的矩形,甚至從不打擾設計師。 – ctacke