MDI дочерние формы медленно рисовать, когда видимость изменилась - PullRequest
3 голосов
/ 31 мая 2010

Мое приложение имеет следующую конфигурацию интерфейса:

Основная форма - это контейнер MDI. Его дочерние формы прикреплены к TabStrip.

У каждого пользователя есть свой набор дочерних форм. В зависимости от активного пользователя отображаются только дочерние формы этого пользователя вместе с вкладками.

Это достигается путем просмотра MdiChildren основной формы и установки для их свойства Visible значения false/true в зависимости от активного пользователя.

        foreach (Form item in MdiChildren)
        {
            if (((OfficeFormEx)item).UserID == (int)e.NewTab.Tag)
            {
                item.Visible = true;
            }
            else
            {
                item.Visible = false;
            }
        }

Это имеет два нежелательных эффекта. Одна из них заключается в том, что каждая дочерняя форма перерисовывается последовательно, что уродливо и медленно. Другой заключается в том, что по какой-то причине формы переходят от максимизированных к нормальным, эффективно отрывая их от основной формы.

Есть ли способ отобразить только одну из дочерних форм, например ту, на которую ранее смотрел пользователь, и заставить другие остаться в фоновом режиме? Максимальное / нормальное значение не так уж и много, потому что я могу снова максимизировать их вручную.

Ответы [ 3 ]

2 голосов
/ 31 мая 2010

Ваш вопрос не очень понятен без фрагмента кода. Однако вы боретесь с реализацией Windows MDI. Одна вещь, которую он не поддерживает, это скрытие дочернего окна, его можно свернуть только в лучшем случае. Windows Forms реализует свойство Visible, уничтожая дескриптор Window, воссоздая его, когда свойство Visible снова устанавливается в True. Этот новый экземпляр окна не будет развернут.

Также не поддерживается переключение фокуса на дочернее окно, когда текущее окно развернуто. Обходной путь WF для этого состоит в том, чтобы вернуть активное дочернее окно в нормальное состояние.

Модель MDI просто не очень подходит для отображения дочерних окон в развернутом состоянии. Чтобы получить интерфейс с вкладками, используйте TabControl и отображайте UserControls на его вкладках.

2 голосов
/ 31 мая 2010

На первый взгляд, я бы посмотрел на свойство Form.WindowsState, если вы еще этого не сделали. Я сомневаюсь, что если вам случится установить это свойство на FormWindowState.Maximized в дизайне, это будет изменено при установке их Visible свойства true / false.

Для "[...] каждая дочерняя форма перерисовывается подряд [...]" - пытались ли вы использовать метод SuspendLayout() в начале активного пользователя проверка формы и вызов ResumeLayout() впоследствии?

РЕДАКТИРОВАТЬ # 1

  • Я бы посоветовал вам загрузить только необходимые Form для текущего пользователя.

Это уменьшит объем памяти, используемой вашим приложением, а также значительно уменьшит количество форм, содержащихся в свойстве MdiChildren collection. Тогда итерация по коллекции, если она все еще требуется, будет быстрее.

Если это не вариант для вас, то, возможно, поможет Linq :

var visibleForms = from f in MdiChildren
                   where (((OfficeFormEx)f).UserID == (int)e.NewTab.Tag)
                   select f;

var invisibleForms = from f in MdiChildren
                     where (((OfficeFormEx)f).UserID != (int)e.NewTab.Tag)
                     select f

visibleForms.ToList().ForEach(f => f.Visible = true);
invisibleForms.ToList().ForEach(f => f.Visible = false);

Если вы используете .NET 4.0, возможно, это будет хорошим кандидатом на PLINQ

Пожалуйста, оставьте отзыв, чтобы мы могли прийти к решению. =)

1 голос
/ 27 сентября 2010

Я в конце концов решил эту проблему, так что вот запоздалая рецензия.

Уилл Маркуиллер предложил SuspendLayout() и ResumeLayout(), которые не сработали. Это заставило меня исследовать, что на самом деле делают эти два метода, и прийти к выводу, что мне нужен был способ предотвратить перерисовку основной формы во время выполнения операций над детьми MDI.

Это, в свою очередь, привело к следующим двум статическим служебным методам, которые приостанавливают перерисовку для данного элемента управления. В моем случае приостановка перерисовки основной формы привела к огромному ускорению.

/// <summary>
/// suspends drawing on a control and its children
/// </summary>
/// <param name="parent"></param>
public static void SuspendDrawing(Control control)
{
    SendMessage(control.Handle, WM_SETREDRAW, false, 0);
}

/// <summary>
/// resumes drawing on a control and its children
/// </summary>
/// <param name="parent"></param>
public static void ResumeDrawing(Control control)
{
    SendMessage(control.Handle, WM_SETREDRAW, true, 0);
    control.Refresh();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...