How to catch the ending resize window?

后端 未结 5 661
[愿得一人]
[愿得一人] 2020-12-08 05:42

I need catch the event endresize in WPF.

5条回答
  •  萌比男神i
    2020-12-08 06:18

    You can detect exactly when a WPF window resize ended, and you don't need a timer. A native window receive the WM_EXITSIZEMOVE message when the user release the left mouse button at the end of a window resize or move operation. A WPF window doesn't receive this message, so we need to hook up a WndProc function which will receive it. We can use HwndSource with WindowInteropHelper to get our window handle. Then we will add the hook to our WndProc function. We will do all that in the window Loaded event (vb.net code):

    Dim WinSource As HwndSource    
    
    Private Sub WindowLoaded_(sender As Object, e As RoutedEventArgs)
    
        WinSource = HwndSource.FromHwnd(New WindowInteropHelper(Me).Handle)
        WinSource.AddHook(New HwndSourceHook(AddressOf WndProc))
    End Sub
    

    Now, in our WndProc, we will listen to the WM_EXITSIZEMOVE message:

    Const WM_EXITSIZEMOVE As Integer = &H232
    
    Private Function WndProc(hwnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
    
        If msg = WM_EXITSIZEMOVE Then
    
            DoWhatYouNeed()
        End If
    
        Return IntPtr.Zero
    End Function
    

    This and a similar technique is explained here and here.

    Notice that the function should return IntPtr.Zero. Also, don't do in this func anything except handling the specific messages you are interested in.

    Now, WM_EXITSIZEMOVE is also sent at the end of a move operation, and we are interested only in resize. There are several ways to determine that this was the end of resize operation. I did it by listening to the WM_SIZING message (which sent many times during resize), combined with a flag. The whole solution looks like this:

    (Note: Don't get confused with the code highlighting here, cause its wrong for vb.net)

    Dim WinSource As HwndSource
    Const WM_SIZING As Integer = &H214
    Const WM_EXITSIZEMOVE As Integer = &H232
    
    Dim WindowWasResized As Boolean = False
    
    Private Sub WindowLoaded_(sender As Object, e As RoutedEventArgs)
    
        WinSource = HwndSource.FromHwnd(New WindowInteropHelper(Me).Handle)
        WinSource.AddHook(New HwndSourceHook(AddressOf WndProc))
    End Sub
    
    Private Function WndProc(hwnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
    
        If msg = WM_SIZING Then
    
            If WindowWasResized = False Then
    
                'indicate the the user is resizing and not moving the window
                WindowWasResized = True
            End If
        End If
    
        If msg = WM_EXITSIZEMOVE Then
    
            'check that this is the end of resize and not move operation          
            If WindowWasResized = True Then
    
                 DoWhatYouNeed()
    
                 'set it back to false for the next resize/move
                 WindowWasResized = False
            End If            
        End If
    
        Return IntPtr.Zero
    End Function
    

    That's it.

提交回复
热议问题