Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my WPF hosted WinForm blank?

I have used the code from this blog, as below but abridged, and I see the WinForm inside my main window, but the sample text I placed on it in a label is not visible.

[System.Windows.Markup.ContentProperty("Child")]
public class WinFormsHost : HwndHost
{
  public WinFormsHost()
  {
    var form = new ChildForm();
    Child = form;
  }
  private System.Windows.Forms.Form child;
  public event EventHandler<ChildChangedEventArgs> ChildChanged;
  public System.Windows.Forms.Form Child
  {
    get { return child; }
    set
    {
      HwndSource ps = PresentationSource.FromVisual(this) as HwndSource;
      if (ps != null && ps.Handle != IntPtr.Zero)
      {
        throw new InvalidOperationException("Cannot set the Child property after the layout is done.");
      }
      Form oldChild = child;
      child = value;
      OnChildChanged(oldChild);
    }
  }

  private void CheckChildValidity()
  {
    if (child == null || child.Handle == IntPtr.Zero)
    {
      throw new ArgumentNullException("child form cannot be null");
    }
  }

  public Boolean ShowCaption
  {
    get
    {
      CheckChildValidity();
      return (GetWindowStyle(Child.Handle) & WindowStyles.WS_BORDER) == WindowStyles.WS_CAPTION;
    }
    set
    {
      if (child == null)
      {
        this.ChildChanged += delegate
        {
          if (value)
          {
            SetWindowStyle(Child.Handle, GetWindowStyle(Child.Handle) | WindowStyles.WS_CAPTION);
          }
          else
          {
            SetWindowStyle(Child.Handle, GetWindowStyle(Child.Handle) & ~WindowStyles.WS_CAPTION);
          }
        };
      }
      else
      {
        if (value)
        {
          SetWindowStyle(Child.Handle, GetWindowStyle(Child.Handle) | WindowStyles.WS_CAPTION);
        }
        else
        {
          SetWindowStyle(Child.Handle, GetWindowStyle(Child.Handle) & ~WindowStyles.WS_CAPTION);
        }
      }
    }
  }

  protected override HandleRef BuildWindowCore(HandleRef hwndParent)
  {
    CheckChildValidity();
    HandleRef childHwnd = new HandleRef(Child, child.Handle);
    SetWindowStyle(childHwnd.Handle, WindowStyles.WS_CHILD | GetWindowStyle(childHwnd.Handle));
    WindowsFormsHost.EnableWindowsFormsInterop();
    System.Windows.Forms.Application.EnableVisualStyles();
    SetParent(childHwnd.Handle, hwndParent.Handle);
    return childHwnd; 
  }
}

And:

<Window x:Class="WinFormsHost" 
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" 
   xmlns:cc="clr-namespace:XTime.Shell.WinformsHost" 
   Title="Hosting Form In WPF">
  <cc:WinFormsHost ShowCaption="False">
    <wf:Form/>
  </cc:WinFormsHost>
</Window>
like image 554
ProfK Avatar asked Dec 20 '13 07:12

ProfK


People also ask

Is WinForm still supported?

Win Form has been used to develop many applications. Because of its high age (born in 2003), WinForm was officially declared dead by Microsoft in 2014.


1 Answers

  <cc:WinFormsHost ShowCaption="False">
    <wf:Form/>
  </cc:WinFormsHost>

Your XAML embeds a System.Windows.Forms.Form object inside the WinFormsHost. Which is what you got, just a blank form with no child controls embedded inside it. It looks like you made an attempt at creating your own in the WinFormsHost constructor, assigning the Child property, but your XAML is overriding it so you are just left with a blank form again.

I put a ChildForm class inside the same namespace:

using System.Windows.Forms;
using System.Drawing;
...

public class ChildForm : System.Windows.Forms.Form {
    public ChildForm() {
        this.BackColor = Color.FromKnownColor(KnownColor.Window);
        var lbl = new Label { Text = "Hello world" };
        this.Controls.Add(lbl);
    }
}

And updated the XAML to:

<cc:WinFormsHost ShowCaption="False">
    <cc:ChildForm/>
</cc:WinFormsHost>

To get:

enter image description here

Set the FormBorderStyle to None to get rid of the border. Etcetera.

Setting the form's TopLevel property to false and Visible property to true is the much simpler way to turn a Form into a child control btw. I left it this way since you hinted you might want to give a Delphi window the same treatment. In which case you might want to go back to your original approach again, creating the child in the form class constructor and just omitting the content assignment in the XAML.

like image 72
Hans Passant Avatar answered Sep 21 '22 08:09

Hans Passant