2012-06-30 27 views
7

透明な境界線を持つイメージをコントロールの背景として表示しようとしました。次のように透明な背景を使用した描画コントロール

残念ながら、透明な領域は、親フォームに穴を作成します:上の画像で

、フォームは私が私のコントロールの後ろに見ることを望んだのだ赤色の背景を持っています透明な領域。次のように

Iが使用されるコードである:私はONMOUSEMOVEおよびonMouseUpのイベントを実装する制御を必要とするので

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); 
    } 

このクラスはピクチャから継承されています。

私は、さまざまなアイデアをテストすることなく、ほとんどの時間を研究していますが、残念なことに、大部分は.Net CFではなくフルフレームワークでのみ動作します。

アイデアをいただければ幸いです。

答えて

6

ああ、CF透明性の喜び。私はそれについて(そして、私は年前にin my blogProject Resistance codeを持っていた)ことができます。

要点はこれです。子コントロールはその領域をペイントする必要がありますが、最初にそれを親(フォームのフォーム)にコールバックして、子のクリッピング領域を除くすべての場所のバックグラウンドイメージを再描画し、その上に描画します。もしそれが少し混乱していると思われるなら、それはそうだからです。

例えば、Project Resistanceを見ると、ビュー(単なるコントロール)は抵抗とバンドを描画します。これは、画像の背景を持つフォームにあり、その背景には、抵抗の透明部分「を通して見え」する必要があります:それはこのない抵抗の描画コードでそう

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); 
    } 
} 

あなたはそれがコントロールと呼ばれるコンテナに実際にあるbecuse(それはこの場合にはparent.parentはがFormのPaintBackgroundを呼び出している見ることができますワークスペース - あなたのケースで2回歩く必要はありません)。それは、あなたが現在「穴」と見ている領域の背景画像を引きます。

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

うわー、ありがとう。非常に有用で詳細な説明。あなたは確かにそのテーマにしばらく時間を費やしました。 –

+0

@ctacke私はあなたのものに非常に近いTransparencyソリューションを考え出しました。これはデザイナーだけでなく実行時にも機能します。私は最近、 "Parent.Parent"のことが機能しないため、Container Controlsをネストするときに私のソリューションが動作しないことに気付きました。私は、 "Parent.Parent"をthis.TopLevelControlに切り替えることを試みました。これは実行時には動作しますが、設計時には動作しません。コンテナコントロール内に透明なコントロールを入れ子にするためのソリューションを手に入れたことがありますが、デザイナーはまだコントロールを透明にしていますか? –

+0

私は何年も前に自分のコントロールのデザイナーのサポートを受けることをやめようとしました。それは私にとってそれほど重要ではなかったし、常に壊れやすいものでした。時にはそれはうまくいくでしょうし、そうでない時もありました。私は実際には何もしませんでしたので、デザイナーはコントロールが行き渡る矩形をレイアウトするのに苦労しませんでした。 – ctacke