В WPF как можно нарисовать линию над WindowsFormsHost?
-
06-07-2019 - |
Вопрос
Вот мой 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?
Решение
Microsoft называет это «воздушным пространством». это предотвращает это, по крайней мере, легко. Вот страница взаимодействия WPF, описывающая воздушное пространство . [Он имеет фокус DX, но то же самое относится, в точности как указано, к WindowsFormsHost.]
WindowsFormsHost (когда у него есть дочерний элемент) создает отдельный HWND, который предотвращает отображение контекста визуализации WPF в этом прямоугольнике.
Для оптимального решения этой проблемы требуется .NET 3.5sp1 (по крайней мере, для надежной работы). Вы можете обойти это, создав полностью отдельное, на 100% прозрачное фоновое окно, и разместив его над своими окнами, формирует хост-контроль. Затем вы включаете это, и оно будет отображаться правильно.
Это немного хакерское чувство, но оно работает.
Другие советы
У меня возникла та же проблема, и после полного поиска я также использовал прозрачное окно «Наложение» поверх 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;
}
Принятый ответ работает. Однако единственная проблема в том, что прозрачное окно будет отображаться поверх моего главного окна. Мне также пришлось подключиться к движению, чтобы убедиться, что все синхронизировано.
Я сделал что-то немного отличное от прозрачного окна. В моем случае это сработало, но не всегда работает.
Я создал пользовательский элемент управления Windows Form. Я поместил текстовое поле и рисование линий на окнах формы пользовательского контроля. Это позволило мне рисовать и отображать в приложении WPF с помощью WindowsFormsHost.