Question

Here is my XAML

<Grid
    Name="grid">
    <TextBlock
        Text="Some Label" />
    <WindowsFormsHost
        Name="winFormsHost">

    </WindowsFormsHost>
</Grid>

On the load of the form I execute the following method

protected void OnLoad(object sender, RoutedEventArgs e)
{
    // Create a line on the fly
    Line line = new Line();

    line.Stroke = Brushes.Red;
    line.StrokeThickness = 17;

    line.X1 = 50;
    line.Y1 = 50;

    line.X2 = 250;
    line.Y2 = 50;

    this.grid.Children.Add(line);

    System.Windows.Forms.TextBox oldSchoolTextbox = new System.Windows.Forms.TextBox();
    oldSchoolTextbox.Text = "A bunch of Random Text will follow.  ";
    oldSchoolTextbox.WordWrap = true;
    oldSchoolTextbox.Width = 300;

    for (int i = 0; i < 250; i++)
    {
        oldSchoolTextbox.Text += "abc ";

        if (i % 10 == 0)
        {
            oldSchoolTextbox.Text += Environment.NewLine;
        }
    }

    this.winFormsHost.Child = oldSchoolTextbox;
}

The line only draws when I comment out the following line.

this.winFormsHost.Child = oldSchoolTextbox;

How do I draw a line over the WindowsFormsHost control?

Was it helpful?

Solution

There is something Microsoft has called "airspace" that prevents this from happening, at least easily. Here is the WPF Interop page describing airspace. [It has a DX focus, but the same thing applies, exactly as stated, to WindowsFormsHost.]

WindowsFormsHost (when it has a child) creates a separate HWND, which prevents the WPF rendering context from displaying in that rectangle.

The best option for working around this requires .NET 3.5sp1 (at least to work reliably). You can get around this by creating an entirely separate, 100% transparent background window, and placing it over your windows forms host control. You then draw into that, and it will display correctly.

It's somewhat hacky feeling, but it works.

OTHER TIPS

I've had the same problem, and after searching all over also ended up using the transparent 'overlay' window on top of the WindowsFormsHost. To keep your main window synchronized with the overlay window you need to handle the following events:

LocationChanged event for your MainWindow and LayoutUpdated event for your WindowsFormsHost element. Both these event handlers should call a function that moves your transparent overlay window on top of the WindowsFormsHost window (SyncOverlayPosition() in the example below).

private void Window_Loaded(object sender, RoutedEventArgs e)
{
   this.LocationChanged += new EventHandler(MainWindow_LocationChanged);
   _windowsFormsHost.LayoutUpdated += new EventHandler(_windowsFormsHost_LayoutUpdated);
}

void MainWindow_LocationChanged(object sender, EventArgs e)
{
   SyncOverlayPosition();
}

void _windowsFormsHost_LayoutUpdated(object sender, EventArgs e)
{
   SyncOverlayPosition();
}

void SyncOverlayPosition()
{
   Point hostTopLeft = _windowsFormsHost.PointToScreen(new Point(0, 0));    

   _overlayWindow.Left = hostTopLeft.X;
   _overlayWindow.Top = hostTopLeft.Y;
   _overlayWindow.Width = _windowsFormsHost.ActualWidth;
   _overlayWindow.Height = _windowsFormsHost.ActualHeight;
}

The accepted answer does work. However the only issue with it is that the transparent window would be displayed over my main window. I also had to hook into movement to make sure everything stayed in sync.

I did something slightly different than a transparent window. This worked in my case, but may not always work.

I created a Windows Form user control. I put the textbox and the line drawing on the windows form user control. This then enabled me to draw over it and display in a WPF application using the WindowsFormsHost.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top