Событие, когда окно разворачивается / не разворачивается

Есть ли событие, которое запускается, когда вы разворачиваете форму или не разворачиваете ее?

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


person Michael Stum    schedule 18.08.2009    source источник
comment
Вы можете проверить местоположение, но возникает вопрос, какое событие запустит ваш тест ...   -  person Sampson    schedule 18.08.2009
comment
Поможет ли тестирование состояния окна в событии активации формы?   -  person Beth    schedule 19.08.2009
comment
Под не максимизированным вы, вероятно, имеете в виду восстановленный.   -  person Andreas Rejbrand    schedule 01.08.2010


Ответы (9)


Вы можете сделать это, переопределив WndProc:

protected override void WndProc( ref Message m )
{
    if( m.Msg == 0x0112 ) // WM_SYSCOMMAND
    {
        // Check your window state here
        if (m.WParam == new IntPtr( 0xF030 ) ) // Maximize event - SC_MAXIMIZE from Winuser.h
        {
              // THe window is being maximized
        }
    }
    base.WndProc(ref m);
}

Это должно обрабатывать событие в любом окне. SC_RESTORE - это 0xF120, а SC_MINIMIZE - 0XF020, если вам тоже нужны эти константы.

person Reed Copsey    schedule 18.08.2009
comment
Вы можете заметить, что это не работает при развертывании двойным щелчком по строке заголовка. Согласно MSDN, в сообщениях WM_SYSCOMMAND четыре младших бита параметра wParam используются системой внутри системы. Чтобы получить правильный результат при проверке значения wParam, приложение должно объединить значение 0xFFF0 со значением wParam с помощью побитового оператора AND. (msdn.microsoft.com/ en-us / library / windows / desktop /) Следовательно, сравнение должно быть (m.WParam.ToInt32 () & 0xFFF0) == 0xF030 или что-то подобное. - person Kevin Ivarsen; 13.11.2012
comment
int wParam = (m.WParam.ToInt32 () & 0xFFF0); если (wParam == 0xF030 || wParam == 0xF020 || wParam == 0xF120) {DoUpdate (); } работал у меня. Также я назвал base.WndProc (ref m); прежде, чем можно будет использовать обновленные параметры окна - person Gorkem; 28.04.2014
comment
См. Ответ Лоренцо для модификации, которая также обрабатывает событие восстановления. (Я думаю, полезно явно указать в примере кода). - person winwaed; 14.05.2017
comment
0xF120 - при разворачивании из панели Windows - person k4yaman; 19.10.2017
comment
работает корректно, при модификации по предложению Горкема - person smirkingman; 17.03.2018

Удивительно, но никто не упомянул встроенный метод .NET.

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

Он даже фиксирует события развертывания / восстановления, вызванные двойным щелчком по заголовку окна, чего метод WndProc не делает.

Скопируйте его и свяжите с обработчиком события «Изменить размер» в форме.

    FormWindowState LastWindowState = FormWindowState.Minimized;
    private void Form1_Resize(object sender, EventArgs e) {

        // When window state changes
        if (WindowState != LastWindowState) {
            LastWindowState = WindowState;


            if (WindowState == FormWindowState.Maximized) {

                // Maximized!
            }
            if (WindowState == FormWindowState.Normal) {

                // Restored!
            }
        }

    }
person Robin Rodricks    schedule 18.05.2013
comment
Спасибо. Это решение выглядит намного красивее, чем переход на уровень WinAPI. Имеет гораздо больше шансов работать с Mono. - person Ivan; 02.03.2014
comment
Этот ответ не касается фактического вопроса, который касался того факта, что событие изменения размера даже не срабатывает при определенных обстоятельствах. - person Dave Cousineau; 13.03.2015

Еще одно небольшое дополнение для проверки восстановления исходного размера и положения после максимизации:

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    // WM_SYSCOMMAND
    if (m.Msg == 0x0112)
    {
        if (m.WParam == new IntPtr(0xF030) // Maximize event - SC_MAXIMIZE from Winuser.h
            || m.WParam == new IntPtr(0xF120)) // Restore event - SC_RESTORE from Winuser.h
        {
            UpdateYourUI();
        }
    }
}

Надеюсь на эту помощь.

person Lorenzo Melato    schedule 01.08.2010

Я считаю, что код еще проще. Вам не нужно сохранять lastState, потому что WindowState проверяется в любое время при запуске события.

 private void MainForm_Resize(object sender, EventArgs e)
    {
        if (WindowState == FormWindowState.Maximized)
        {
            spContainer.SplitterDistance = 1000;
        }
        if (WindowState == FormWindowState.Normal)
            spContainer.SplitterDistance = 500;
    }
person Gabriel Marius Popescu    schedule 17.02.2017

У меня была такая же проблема, и я мог ее решить, не отменяя. Поскольку у меня есть PictureBox в режиме док-станции «Заливка», я могу использовать его событие SizeChanged, которое также запускается при максимальном увеличении окна.

person 816-8055    schedule 13.01.2013

Надеюсь, эта часть кода будет вам полезна.

            if (m.Msg == User32.WM_WINDOWPOSCHANGING && IsHandleCreated)
            {
                User32.WINDOWPLACEMENT wp = new User32.WINDOWPLACEMENT();
                wp.length = Marshal.SizeOf(typeof(User32.WINDOWPLACEMENT));
                User32.GetWindowPlacement(Handle, ref wp);

                switch (wp.showCmd)
                {
                    case User32.SW_RESTORE:
                    case User32.SW_NORMAL:
                    case User32.SW_SHOW:
                    case User32.SW_SHOWNA:
                    case User32.SW_SHOWNOACTIVATE:
                        _windState = FormWindowState.Normal;
                        if (wp.showCmd == User32.SW_RESTORE)
                            Update();
                        break;

                    case User32.SW_SHOWMAXIMIZED:
                        _windState = FormWindowState.Maximized;
                        SetMaximumSize();

                        break;

                    case User32.SW_SHOWMINIMIZED:
                    case User32.SW_MINIMIZE:
                    case User32.SW_SHOWMINNOACTIVE:
                        _windState = FormWindowState.Minimized;
                        break;
                }
            }

    private void SetMaximumSize()
    {
        Screen screen = Screen.FromControl(this);
        if (screen != null && !screen.WorkingArea.IsEmpty)
        {
            int sizeDiff = this.Size.Width - this.ClientSize.Width;
            var maxSize = new Size(screen.WorkingArea.Width + sizeDiff, screen.WorkingArea.Height + sizeDiff);
            this.MaximumSize = maxSize;
        }
    }

    #region Window State

    public const int SW_NORMAL = 1,
        SW_SHOWMINIMIZED = 2,
        SW_SHOWMAXIMIZED = 3,
        SW_SHOWNOACTIVATE = 4,
        SW_SHOW = 5,
        SW_MINIMIZE = 6,
        SW_SHOWMINNOACTIVE = 7,
        SW_SHOWNA = 8,
        SW_RESTORE = 9;

    #endregion Window State
person Track    schedule 09.06.2017

Если нет очевидного события для прослушивания, вам, вероятно, придется подключиться к Windows API и поймать соответствующее сообщение (Google обнаруживает, что вы хотите перехватить сообщение WM_SYSCOMMAND: http://www.codeguru.com/forum/archive/index.php/t-234554.html).

person Matt    schedule 18.08.2009

Я здесь новичок, поэтому комментарии запрещены, но это комментарий к чистому ответу GeoTarget:

Первая строка OUGHT должна быть слегка изменена на nullable, чтобы поймать, если форма запущена Minimized:

FormWindowState? LastWindowState = null;

И банальное предложение: переместите присвоение LastWindowState в после "if", чтобы пользователь мог легко проверить не только то, к чему вы переходите, но и откуда оно взялось:

FormWindowState? LastWindowState = null;
private void Form1_Resize(object sender, EventArgs e) {
    // When window state changes
    if (WindowState != LastWindowState) {
        if (WindowState == FormWindowState.Maximized) {
            // Maximized!
        }
        if (WindowState == FormWindowState.Normal) {
            // Restored!
        }
        LastWindowState = WindowState;
    }
}
person Eske Rahn    schedule 24.06.2015

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

protected override void WndProc(ref Message m)
{
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_MAXIMIZE = 0xF030;
    const int SC_MINIMIZE = 0xF020;
    const int SC_RESTORE = 0xF120;

    // dependig on the needs may be called before, after or even never (see below)
    // base.WndProc(ref m);

    if (m.Msg == WM_SYSCOMMAND)
    {
        /// <see cref="https://docs.microsoft.com/en-us/windows/win32/menurc/wm-syscommand"/>
        /// Quote:
        /// In WM_SYSCOMMAND messages, the four low - order bits of the wParam parameter 
        /// are used internally by the system.To obtain the correct result when testing 
        /// the value of wParam, an application must combine the value 0xFFF0 with the 
        /// wParam value by using the bitwise AND operator.
        int wParam = (m.WParam.ToInt32() & 0xFFF0);

        Debug.WriteLine($"Received param: { Convert.ToString(wParam, 16) } ");

        if (wParam == SC_MAXIMIZE)
        {

        }

        if (wParam == SC_MINIMIZE)
        {

        }

        if (wParam == SC_RESTORE)
        {

        }
    }

    // don't use when above call is uncommented
    base.WndProc(ref m);
}
person marsh-wiggle    schedule 19.06.2020