none
How to determine when a user finishes resizing a WPF window?

    Question

  • I have an app that needs to create a new image when a user resizes a window. I need to know when the user finishes resizing.

    How can this be done in WPF?

    Cheers,

    MikeS
    Wednesday, April 25, 2007 2:33 PM

Answers

  • Update: I solved the problem by P/Invoking to GetAsyncKeyState and using VK_LBUTTON to check the mouse left button state. It would be nice if the WPF Mouse class already had this functionality, or if the Key enumeration included values for the mouse buttons so that Keyboard.GetKeyStates could be used.

    For anyone else who's looking for this functionality:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Threading;

    namespace MouseDownState
    {
        public partial class Window1 : System.Windows.Window
        {
            [DllImport( "user32.dll" )]
            static extern short GetAsyncKeyState( int vKey );

            public const int VK_LBUTTON = 0x01;

            public Window1()
            {
                InitializeComponent();
                new DispatcherTimer(
                    TimeSpan.FromMilliseconds( 100 ), DispatcherPriority.Normal,
                    delegate
                        {
                            bool mouseIsDown = GetAsyncKeyState( VK_LBUTTON ) < 0;
                            stateLabel.Content = "Mouse is " + ( mouseIsDown ? "down" : "up" ) ;
                        },
                    Dispatcher );
            }
        }
    }

    <Window x:Class="MouseDownState.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MouseDownState" Height="300" Width="300"
        >
      <StackPanel>
        <Label Name="stateLabel" FontSize="30"/>
      </StackPanel>
    </Window>
    Thursday, April 26, 2007 1:12 PM

All replies

  • There is no event which is raised when the user is finished resizing a Window.  The SizeChanged event will be raised (as a result of the protected OnRenderSizeChanged being invoked) many times during a resizing gesture, so to speak.  What you can do is start a DispatcherTimer when the Window is resized.  Every time the resizing occurs, restart the timer.  When the timer ticks, perform whatever "post-resizing" logic your application needs, and stop the timer.

     

    HTH

    Wednesday, April 25, 2007 3:04 PM
  • Thanks.

    I'm using a timer now, but it's not nice as there's a delay between finishing resizing and updating the background image.

    Is there no way to detect the global mouse button state? Mouse.LeftButton is always Released while resizing.

    How about intercepting WM_NCLBUTTONUP? Is there an easy way to do this in WPF?

    MikeS.
    • Proposed as answer by Mats Gisselson Monday, February 11, 2013 12:37 PM
    Wednesday, April 25, 2007 3:35 PM
  • If you need to intercept window messages in WPF, you can use your own WPF window WndProc. The following blog entry nicely shows the basics: https://blogs.msdn.com/nickkramer/archive/2006/03/18/554235.aspx

    Wednesday, April 25, 2007 3:45 PM
  • Update: I solved the problem by P/Invoking to GetAsyncKeyState and using VK_LBUTTON to check the mouse left button state. It would be nice if the WPF Mouse class already had this functionality, or if the Key enumeration included values for the mouse buttons so that Keyboard.GetKeyStates could be used.

    For anyone else who's looking for this functionality:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Threading;

    namespace MouseDownState
    {
        public partial class Window1 : System.Windows.Window
        {
            [DllImport( "user32.dll" )]
            static extern short GetAsyncKeyState( int vKey );

            public const int VK_LBUTTON = 0x01;

            public Window1()
            {
                InitializeComponent();
                new DispatcherTimer(
                    TimeSpan.FromMilliseconds( 100 ), DispatcherPriority.Normal,
                    delegate
                        {
                            bool mouseIsDown = GetAsyncKeyState( VK_LBUTTON ) < 0;
                            stateLabel.Content = "Mouse is " + ( mouseIsDown ? "down" : "up" ) ;
                        },
                    Dispatcher );
            }
        }
    }

    <Window x:Class="MouseDownState.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MouseDownState" Height="300" Width="300"
        >
      <StackPanel>
        <Label Name="stateLabel" FontSize="30"/>
      </StackPanel>
    </Window>
    Thursday, April 26, 2007 1:12 PM
  • Seems to me that the best solution would be:

    -set some boolean to true when resize event occurs

    -hook Window WM_NCLBUTTONUP

    -in message response check boolean and if set assume resizing has ended. Do what needs to be done. Set boolean to false.

    Thursday, April 26, 2007 4:44 PM
  • Here is an implementation of Josh's suggestion. It works really well and you don't have to deal with low level windows junk

    public MyUserControl()
    {
        _resizeTimer.Tick += _resizeTimer_Tick;
    }
    
    DispatcherTimer _resizeTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 0, 1500), IsEnabled = false };
    
    private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        _resizeTimer.IsEnabled = true;
        _resizeTimer.Stop();
        _resizeTimer.Start();
    }
    
    int tickCount = 0;
    void _resizeTimer_Tick(object sender, EventArgs e)
    {
        _resizeTimer.IsEnabled = false;
        //you can get rid of this, it just helps you see that this event isn't getting fired all the time
        Console.WriteLine("TICK" + tickCount++);
    
        //Do important one-time resizing work here
        //...
    }
    

    Saturday, March 06, 2010 11:11 PM