在WPF中,如何在WindowsFormsHost上划一条线?

时间:2022-08-25 22:05:27

Here is my XAML

这是我的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?

如何在WindowsFormsHost控件上绘制一条线?

3 个解决方案

#1


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.]

微软称之为“空域”的东西可以防止这种情况发生,至少很容易。这是描述空域的WPF Interop页面。 [它有一个DX焦点,但完全相同的事情适用于WindowsFormsHost。]

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

WindowsFormsHost(当它有一个子节点时)创建一个单独的HWND,它可以防止WPF渲染上下文显示在该矩形中。

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.

解决此问题的最佳选择需要.NET 3.5sp1(至少可靠地工作)。您可以通过创建一个完全独立的100%透明背景窗口并将其放在Windows窗体主机控件上来解决这个问题。然后你绘制它,它将正确显示。

It's somewhat hacky feeling, but it works.

这有点hacky的感觉,但它的工作原理。

#2


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:

我遇到了同样的问题,搜索完毕后最终也使用了WindowsFormsHost顶部的透明“覆盖”窗口。要使主窗口与覆盖窗口保持同步,您需要处理以下事件:

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).

适用于WindowsFormsHost元素的MainWindow和LayoutUpdated事件的LocationChanged事件。这两个事件处理程序都应调用一个函数,将透明覆盖窗口移动到WindowsFormsHost窗口的顶部(下例中的SyncOverlayPosition())。

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

#3


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.

我创建了一个Windows窗体用户控件。我把文本框和线条图放在windows窗体用户控件上。这使我能够使用WindowsFormsHost绘制它并显示在WPF应用程序中。

#1


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.]

微软称之为“空域”的东西可以防止这种情况发生,至少很容易。这是描述空域的WPF Interop页面。 [它有一个DX焦点,但完全相同的事情适用于WindowsFormsHost。]

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

WindowsFormsHost(当它有一个子节点时)创建一个单独的HWND,它可以防止WPF渲染上下文显示在该矩形中。

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.

解决此问题的最佳选择需要.NET 3.5sp1(至少可靠地工作)。您可以通过创建一个完全独立的100%透明背景窗口并将其放在Windows窗体主机控件上来解决这个问题。然后你绘制它,它将正确显示。

It's somewhat hacky feeling, but it works.

这有点hacky的感觉,但它的工作原理。

#2


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:

我遇到了同样的问题,搜索完毕后最终也使用了WindowsFormsHost顶部的透明“覆盖”窗口。要使主窗口与覆盖窗口保持同步,您需要处理以下事件:

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).

适用于WindowsFormsHost元素的MainWindow和LayoutUpdated事件的LocationChanged事件。这两个事件处理程序都应调用一个函数,将透明覆盖窗口移动到WindowsFormsHost窗口的顶部(下例中的SyncOverlayPosition())。

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

#3


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.

我创建了一个Windows窗体用户控件。我把文本框和线条图放在windows窗体用户控件上。这使我能够使用WindowsFormsHost绘制它并显示在WPF应用程序中。