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

时间:2009-06-17 15:22:44

标签: c# .net wpf drawing windowsformshost

这是我的XAML

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

    </WindowsFormsHost>
</Grid>

在表单的加载中,我执行以下方法

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

当我注释掉以下行时,该行才会绘制。

this.winFormsHost.Child = oldSchoolTextbox;

如何在WindowsFormsHost控件上画一条线?

3 个答案:

答案 0 :(得分:4)

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

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

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

这种感觉有些神圣,但它确实有效。

答案 1 :(得分:2)

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

MainWindow的LocationChanged事件 和 WindowsFormsHost元素的LayoutUpdated事件。这两个事件处理程序都应调用一个函数,将透明覆盖窗口移动到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;
}

答案 2 :(得分:0)

接受的答案确实有效。然而,唯一的问题是透明窗口将显示在我的主窗口上。我还必须动起来确保一切都保持同步。

我做的事情与透明窗口略有不同。这在我的案例中有效,但可能并不总是有效。

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