В WPF как можно нарисовать линию над WindowsFormsHost? - PullRequest
1 голос
/ 17 июня 2009

Вот мой 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 ]

4 голосов
/ 17 июня 2009

Есть что-то, что Microsoft назвала «воздушным пространством», которое, по крайней мере, легко предотвращает это. Вот страница WPF Interop, описывающая воздушное пространство . [Он имеет фокус DX, но то же самое относится, как указано, к WindowsFormsHost.]

WindowsFormsHost (когда у него есть дочерний элемент) создает отдельный HWND, который предотвращает отображение контекста визуализации WPF в этом прямоугольнике.

Для оптимального решения этой проблемы требуется .NET 3.5sp1 (по крайней мере, для надежной работы). Вы можете обойти это, создав полностью отдельное, на 100% прозрачное фоновое окно, и разместив его над своими окнами, формирует хост-контроль. Затем вы включаете это, и оно будет отображаться правильно.

Это немного хакерское чувство, но оно работает.

2 голосов
/ 01 августа 2012

У меня была такая же проблема, и после поиска все закончилось тем, что я использовал прозрачное окно наложения поверх WindowsFormsHost. Чтобы синхронизировать главное окно с оверлейным окном, вам нужно обработать следующие события:

Событие LocationChanged для вашего главного окна а также Событие LayoutUpdated для вашего элемента WindowsFormsHost. Оба эти обработчика событий должны вызывать функцию, которая перемещает ваше прозрачное окно наложения поверх окна 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;
}
0 голосов
/ 18 июня 2009

Принятый ответ работает. Однако единственная проблема в том, что прозрачное окно будет отображаться поверх моего главного окна. Мне также пришлось подключиться к движению, чтобы убедиться, что все синхронизировано.

Я сделал что-то немного отличное от прозрачного окна. Это сработало в моем случае, но не всегда может работать.

Я создал пользовательский элемент управления Windows Form. Я поместил текстовое поле и рисование линий на окнах формы пользовательского контроля. Это позволило мне рисовать и отображать в приложении WPF с помощью WindowsFormsHost.

...