C# Winforms-WPF interop

2019-07-22 02:15发布

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?

2条回答
女痞
2楼-- · 2019-07-22 02:45

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.

查看更多
时光不老,我们不散
3楼-- · 2019-07-22 02:58

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.

查看更多
登录 后发表回答