Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Разработка Windows Forms > как синхронизировать размеры основной формы


Автор: -ser- 4.8.2005, 05:51
основная форма открывает вторую в модальном режиме.
есть идеи как можно синхронизировать под второй основную, делая Resize и Move на второй? т.е. фактически скрыть существование основной пока не выйдут из второй.

Автор: Domestic Cat 4.8.2005, 05:56
Спрячь первую, т.е минимизируй и все.

Автор: -ser- 4.8.2005, 08:58
в принципе, именно то что надо.
минимизирую, убираю с таскбара а при выходе из второй делаю обратное с первой.
только теперь налицо видимая задержка между исчезновением первой и появлением второй и обратно и сразу заметна подмена. но тут уже ничего не поделаешь. посмотрю как скоро это начнет раздражать.

Автор: mr.DUDA 4.8.2005, 10:22
А какая задача при этом решается ? Зачем две формы ?

Может, достаточно сделать 2 юзер контрола, положить их на одну форму, и переключаться между ними с пом. свойства Visible ?

Автор: -ser- 5.8.2005, 07:43
я так и сделал вначале. но поскольку каждая из форм решает настолько разные задачи что каждая должна иметь свое полноценное меню, тоолбар и т.п., т.е. почти ничего общего кроме стиля. и мне пришлось делать merge всего этого а потом копаться в логике. плюс ко всему у меня на обоих формах dockable окна и когда я их делал видимыми и невидимыми, то они выстраивались в нужном порядке так неохотно медленно и заметно, что выглядело уж очень непрофессионально. причем я консультировался с компанией-поставщиком, что здесь можно сделать, они ничего не смогли предложить на тот момент и даже не поставили эту задачу себе в wish list. SuspendLayout и все прочее не проходило. поэтому я решил все это простым способом, причем пока вторая открыта, первая форма не может понадобится, и я подумал, чем модальное плохо? и подмена небыла заметна, но появился тот побочный эффект с синхронизированием размеров форм. я уж думал писать какой-то менеджер по их синхронизации.

Автор: mr.DUDA 5.8.2005, 15:31
Вот решение этой задачи:

Form1 - содержит кнопку, по которой открывается модальная форма Form2:
Код

namespace TwoForms
{
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button button1;
        private System.ComponentModel.Container components = null;

        // ...


        private void button1_Click(object sender, System.EventArgs e)
        {
            Form2 form = new Form2();
            FormSynchronizer.Start(this, form);
            form.ShowDialog(this);
            FormSynchronizer.Stop();
        }
    }
}


Form2 - произвольная форма.

FormSynchronizer.cs - содержит методы Start и Stop, соответственно стартующий и останавливающий отдельный поток, который реагирует на события SizeChanged и LocationChanged от модальной формы, и передвигает/ресайзит форму Form1 в её "родном" потоке (с пом. Form.Invoke):
Код

using System;
using System.Threading;
using System.Drawing;
using System.Windows.Forms;

namespace TwoForms
{
    public class FormSynchronizer
    {
        ///////////////// Public members

        public static void Start(Form idleForm, Form modalForm)
        {
            _modalForm = modalForm;
            _idleForm = idleForm;
            _syncEvent = new AutoResetEvent(false);
            _haveToStop = false;
            _thread = new Thread(new ThreadStart(SynchronizeThread));
            _thread.Start();
            _modalForm.SizeChanged += new EventHandler(modalForm_SizeChanged);
            _modalForm.LocationChanged += new EventHandler(modalForm_LocationChanged);
            _syncEvent.Set(); // синхронизируем формы сейчас
        }

        public static void Stop()
        {
            _modalForm.SizeChanged -= new EventHandler(modalForm_SizeChanged);
            _modalForm.LocationChanged -= new EventHandler(modalForm_LocationChanged);
            _haveToStop = true;
            _syncEvent.Set();
        }

        //////////// Private members

        private delegate void SyncFormsDelegate();
        private static void SynchronizeThread()
        {
            while(true)
            {
                _syncEvent.WaitOne();
                if(_haveToStop) 
                    return; // нормальное завершение потока
                else
                    _idleForm.Invoke(new SyncFormsDelegate(SyncForms));
            }
        }
        private static void SyncForms()
        {
            _idleForm.Location = _modalForm.Location;
            _idleForm.Size = _modalForm.Size;
        }
        private static void modalForm_SizeChanged(object sender, EventArgs e)
        {
            _syncEvent.Set();
        }
        private static void modalForm_LocationChanged(object sender, EventArgs e)
        {
            _syncEvent.Set();
        }


        ///////////// Static fields

        static Form _idleForm = null;
        static Form _modalForm = null;
        static Thread _thread;
        static AutoResetEvent _syncEvent;
        static bool _haveToStop = false;
    }
}

Автор: -ser- 8.8.2005, 08:45
очень даже неплохо.
но если в первой форме установлено FormWindowState.Maximized (а они обе изначально Maximized), то это почему-то не работает. если я явно поменяю состояние первой на Normal перед стартом синхронайзера, тогда срабатывает, но тогда опять заметна видимая перерисовка при открытии второй, особенно при первом вызове.
Код

private void button1_Click(object sender, System.EventArgs e)
{
    Form2 form = new Form2();
    this.WindowState = FormWindowState.Normal;
    FormSynchronizer.Start(this, form);
    form.ShowDialog(this);
    FormSynchronizer.Stop();
}

правда еще побочный эффект в этом случае, не пойму в чем причина.
если я минимизирую вторую ( и затем возвращаю в исходное состояние и пр.), то потом при выходе из нее сбивается расположение dockable windows в первой. но во всех других случаях всевозможных манипуляций со второй ( кроме ее минимизации ) такого не происходит.


Автор: mr.DUDA 8.8.2005, 09:25
Первое "лечится" добавлением в SyncForms одной строчки:
Код

    _idleForm.WindowState = _modalForm.WindowState;


Насчёт второго не знаю, видимо стыковочные окна отдельно обрабатывают минимизацию окна, сохраняя предыдущие размеры до минимизации.

З.Ы. заметил такую вещь: если открыть форму с пом. ShowDialog, то минимизация модальной формы приводит к тому, что её DialogResult становится равным Cancel, что закрывает форму.

Автор: -ser- 8.8.2005, 10:56
если исходить из логики мелких, что любая невидимая форма есть форма закрытая, и добавить нижеследующее, то можно совсем не удивиться, если все заработает примерно так как надо
Код

        private void Form2_VisibleChanged( object sender, EventArgs e )
        {
            if( this.WindowState == FormWindowState.Minimized )
                this.Visible = true;
        }

наверно у них много женщин работает.

Автор: mr.DUDA 8.8.2005, 12:50
Цитата(ser @ 8.8.2005, 10:56)
наверно у них много женщин работает.

smile smile smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)