Как избежать визуальных артефактов при хостинге пользовательских элементов управления WPF в рамках MDI-приложения WinForms?

При хостинге пользовательских элементов управления WPF в рамках MDI-приложения WinForms существует проблема рисунка, когда у Вас есть несколько форм, которые перекрывают друг друга, который вызывает очень отличные визуальные артефакты. Эти артефакты главным образом видимы после перетаскивания одной дочерней формы по другому, который также размещает содержание WPF или позволяя краям дочерней формы быть отсеченным основным родителем MDI при перетаскивании его вокруг. После того, как перетаскивание дочерней формы завершается, артефакты остаются вокруг обычно, но я нашел, что, устанавливая фокус на окно другого приложения и затем перефокусируя назад на моем окне приложения, что это перерисовывается и все хорошо снова, пока дочерние формы не перемещены еще раз. См. изображение, ниже которого демонстрирует проблему.

Screenshot of described artifacts

Те, которые в Microsoft, настаивают, что WinForms MDI уже является достаточным решением для MDI и не нуждается в переосмыслении в WPF, хотя мне трудно полагать, что они пытались создать приложение WPF этот путь из-за очевидных недостатков.

ОБНОВЛЕНИЕ: Несколько дополнительных примечаний, которые я не учел, - то, что, если я создаю эти Формы, не устанавливая MdiParent, они создаются как регулярные формы, и этой проблемы не происходит. Эта проблема кажется уникальной для сценария WinForms MDI. Также я в настоящее время имею работающий на Предприятии Windows 7, и я знаю, что результаты могут очень отличаться на Windows XP, но я не смог протестировать это.

ОБНОВЛЕНИЕ: я нашел несколько других связанных ресурсов по этой проблеме, что я думал, что должен совместно использовать.

6
задан Community 8 February 2017 в 14:23
поделиться

2 ответа

Что ж, возможно, я нашел решение, хотя это похоже на взлом. Похоже, что если вы вызываете метод Refresh для родительского MDI при перемещении дочерней MDI-формы, отмеченные артефакты исчезают. Визуально при перетаскивании окна все выглядит немного нервно, но это кажется гораздо более приемлемым, чем пример, который я показал в моем исходном сообщении.

private void Form1_Move(object sender, EventArgs e)
{
    this.ParentForm.Refresh();

    System.Diagnostics.Debug.WriteLine(string.Format("Form Moved to: ({0},{1})", this.Left, this.Top));
}

Я пробовал много комбинаций в том же духе, например, обновлял только дочернее окно, которое перемещалось, вызывая такие методы, как Update () , Invalidate () , Refresh () , а также я пробовал эти же методы на родительском MDI, а также на Dispatcher.Invoke (DispatcherPriority.Render, ...) и InvalidateVisual () на моем размещенном элементе управления WPF, но ни один из этих других методов не работал, accept для вызова Refresh () специально для родительского элемента MDI.

Я понимаю, что это, вероятно, не оптимальное решение, поскольку я заставляю все главное окно приложения обновляться каждый раз, когда дочернее окно перемещается на несколько пикселей, но на данный момент это единственное разумное решение, которое, как я обнаружил, работает . Если у кого-то еще есть альтернативные решения или какие-либо улучшения, я с радостью приму ваш ответ.

2
ответ дан 9 December 2019 в 20:41
поделиться

Похоже, что еще один обходной путь - вернуться к программному рендерингу, а не использовать преимущества аппаратного ускорения. Это было предложение Марко Чжоу на форумах MSDN.

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        this.Loaded += delegate
        {
            var source = PresentationSource.FromVisual(this);
            var hwndTarget = source.CompositionTarget as HwndTarget;
            if (hwndTarget != null)
            {
                hwndTarget.RenderMode = RenderMode.SoftwareOnly;
            }
        };
    }
}

Я протестировал это, и это решение, похоже, работает очень хорошо, и пока что это единственное решение, которое я нашел для решения этой проблемы в сценарии взаимодействия FoxPro, который очень похож на сценарий WinForms, о котором я писал изначально.На данный момент я планирую использовать свое исходное обновление в родительском решении MDI для моего проекта WinForms, но затем для других моих собственных приложений взаимодействия, например, когда мои элементы управления WPF размещены в Visual FoxPro, я буду использовать это решение. Это если, конечно, не будет найдено более элегантное решение для любого из случаев.

Также важно отметить, что, насколько мне известно, программный рендеринг - единственный вариант в системах XP, и обычно Visual FoxPro nore WinForms обычно используют тот же тип аппаратного ускорения, что и собственные приложения WPF в ОС Vista и выше. . Так что использование этой опции может быть не так плохо, как кажется, когда вам действительно нужно иметь дело с взаимодействием. В настоящее время я не знаю о каких-либо побочных эффектах при использовании этого решения, но если они есть, их необходимо серьезно рассмотреть.

8
ответ дан 9 December 2019 в 20:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: