2

Currently I have a Winforms app which relies on transpareny effects. However this is proving to be an absolute pain in the preverial behind! Winforms as Im learning doesn't deal with transparency particularly well.

I was wondering whether or not this would be any easier using WPF components for the transparency bit and winforms for the rest (note althought Id like to move the whole app over to WPF this just isn't feasable!). I know next to nothing about WPF, hence the reason Im here! What I was considereing was :

1) Host a WPF component within a Winforms User Control e.g. Example of WPF Control:

<UserControl x:Class="WindowsFormsApplication1.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid>
         <Rectangle Name="rectangle1" Stroke="White" Fill="Black" RadiusX="10" RadiusY="10" Opacity="0.7" />
        <Rectangle Margin="57,101,43,99" Name="dialog" Stroke="Gray" Fill="White" RadiusX="10" RadiusY="10" />
    </Grid>
</UserControl>

2) Host a Winforms user control (content) within the white rectangle (dialog) of the WPF control. 3) allow the content (Winforms user control) to call code on the parent of the WPF-Control.

First things first...

  • Is this a reasonable thing to do or am I barking up the wrong tree?
  • Can this be achieved in an easier fashion?
  • Can anyone help me here? (Sample code would be gratefully received!)
  • Finally ... are there any online resources that can help me a) learn WPF and b) become more self-sufficient?
TK.
  • 46,577
  • 46
  • 119
  • 147
  • 1
    @TK: Rendering transparency mixed with WPF and Winforms is a problem, and I don't know if that one's solvable. WPF and WinForms are fundamentally different, and I recall reading somewhere that while they can host eachother, overlaid components will not render correctly, period. They need distinct regions. I believe I read that in Adam Nathan's book, but I don't have it here to reference, so I could be remembering incorrectly. – Greg D Aug 12 '09 at 13:57
  • @Greg D: I believe you are absolutely correct. The problem being that each control (be it WPF or Winforms) requires its own airspace. This is to say that at any given point in time, a pixel on the screen is either a WPF pixel or a Winform Pixel and cant be a hybrid of the two. I have solved this issue by getting the Winforms components to render themselves as a BMP file and then render the bmp file as the background of another control. Messy ... yes but it appears to work well enough. – TK. Aug 12 '09 at 15:01
  • Clever approach. Can you post how you got the winforms controls to render as a bitmap for the blending effects in an answer to your question? :) Do you capture changes in the winforms controls and update the bitmap appropriately as they happen, or are the winforms controls static during the transparency effects? – Greg D Aug 15 '09 at 11:51

2 Answers2

4

It certainly is possible, and I think you are right that it would be the easiest way to work with transparency.

I haven't tried it myself, but according to this article on CodeProject, it should be quite simple. You should use the ElementHost control to host your WPF content.

Hosting WPF in a WinForms control is a supported scenario, a feature built into the framework. So there should be no problems in doing so. There is also a WPF component for going the other way, hosting WinForms in a WPF app.

driis
  • 161,458
  • 45
  • 265
  • 341
  • Thanks for the Link ... its really helped! The only problem now is getting the WPF to render its transparency to show the Winforms controls underneath! At the moment its completely opaque at the moment – TK. Jun 01 '09 at 20:00
1

Here is the solution I used to solve the problem at Hand. This solution relies on the overlaying Control to render its Parent as a bitmap image. This then gets painted as the background of the overlaying control.

public class OverlayingControl : UserControl
{
    /// <summary>
    /// Overrides the c# standard Paint Background to allow the custom background to be drawn 
    /// within the OnPaint function
    /// </summary>
    /// 
    /// <param name="e">Arguements used within this function</param>
    protected override void OnPaintBackground( PaintEventArgs e )
    {
        //Do Nothing 
    }

    protected override void OnPaint( PaintEventArgs e )
    {
        // Render the Parents image to a Bitmap. NB: bitmap dimensions and Parent Bounds can be changed to achieve the desitred effect
        Bitmap background = new Bitmap( Width, Height, PixelFormat.Format64bppArgb );
        Parent.DrawToBitmap( background, Parent.Bounds );

        // Paint background image             
        g.DrawImage( background, 0, 0, new RectangleF( Location, Size ), GraphicsUnit.Pixel );

        // Perform any alpha-blending here by drawing any desired overlay e.g.
        // g.FillRectangle( new SolidBrush( semiTransparentColor ), Bounds);
    }

}

This is performed purely within the WinForms domain, however I believe it could be possible to pass this Bitmap image to a WPF control to render as required. Currently there is no provision for updating the Bitmap when the parent changes, However, it should be trivial to create a custom method that clears the bitmap and re-draws the Overlayng control. Not an elegant solution I realise... but it appears to work well enough.

TK.
  • 46,577
  • 46
  • 119
  • 147