In WPF, I want to handle the start and end of Resize like WinForms

尼龟 杰 150 Reputation points
2023-01-29T14:12:29.06+00:00

I need an event in WPF which can tell me when does the window's border stop being dragged, because I can't run my large code every time SizeChanged event triggers.

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,805 questions
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,635 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
9,979 questions
0 comments No comments
{count} votes

Accepted answer
  1. Reza Aghaei 4,936 Reputation points MVP
    2023-01-29T14:26:48.5733333+00:00

    You can use either of the following options:

    1. You can handle WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE native messages using a HwndSourceHook which is what WinForms does for ResizeBegin and ResizeEnd events.
    2. Or you can use a timer, to debounce the noise of SizeChanged based on a delay.

    Example 1 - WPF Window ResizeBegin and ResizeEnd events like WinForms

    This technique relies on handling WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE native messages using a HwndSourceHook which is pretty similar to what WinForms does:

    using System;
    using System.Windows;
    using System.Windows.Interop;
    using System.Windows.Threading;
    
    namespace WpfApp
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            DispatcherTimer timer = new DispatcherTimer
            {
                Interval = new TimeSpan(0, 0, 0, 0, 500),
                IsEnabled = false
            };
            public MainWindow()
            {
                InitializeComponent();
                this.Loaded += (obj, args) =>
                {
                    var handle = new WindowInteropHelper(this).Handle;
                    var win = HwndSource.FromHwnd(handle);
                    win.AddHook(new HwndSourceHook(WndProc));
                };
            }
    
            private const int WM_ENTERSIZEMOVE = 0x0231;
            private const int WM_EXITSIZEMOVE = 0x0232;
            public event EventHandler ResizeBegin;
            public event EventHandler ResizeEnd;
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                if (msg == WM_ENTERSIZEMOVE)
                {
                    OnResizeBegin();
                    handled = true;
                }
                if (msg == WM_EXITSIZEMOVE)
                {
                    OnResizeEnd();
                    handled = true;
                }
                return IntPtr.Zero;
            }
            private void OnResizeBegin()
            {
                this.Title = "Resize begin ...";
                //Any custom logic for resize begin
            }
            private void OnResizeEnd()
            {
                this.Title = "Resize end.";
                //Any custom logic for resize begin
            }
    
        }
    }
    
    

    Example 2 - WPF Window Debounce the SizeChanged event

    In this example I've used a timer to debounce the SizeChanged event and run a logic after the resize is done. This technique relies on a custom delay (like 500 milliseconds, or anything which fits the requirement), like what is usually used in Hover event:

    public partial class MainWindow : Window
    {
        DispatcherTimer timer = new DispatcherTimer
        {
            Interval = new TimeSpan(0, 0, 0, 0, 500),
            IsEnabled = false
        };
        public MainWindow()
        {
            InitializeComponent();
            timer.Tick += timer_Tick;
            this.SizeChanged += Window_SizeChanged; 
            //Or if you want to handle the SizeChanged
            //this.Loaded+=(obj, args) => this.SizeChanged += Window_SizeChanged; 
        }
        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.Title = "Resizing ...";
            timer.IsEnabled = true;
            timer.Stop();
            timer.Start();
        }
        void timer_Tick(object sender, EventArgs e)
        {
            timer.IsEnabled = false;
            //Resize ended (based on 500 ms debaounce time
            this.Title = "Resize done.";
        }
    }
    

    You can see a few more example or possible solutions here: How to catch the ending resize window?

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Castorix31 80,911 Reputation points
    2023-01-29T15:37:17.0133333+00:00
    1 person found this answer helpful.