我需要捕捉WPF中的事件endresize。如何捕捉結束大小調整窗口?
回答
WPF不提供在調整大小過程結束時單獨觸發的事件。 SizeChanged是與窗口大小調整相關的唯一事件 - 並且在調整大小過程中將多次觸發。
總的來說,當SizeChanged事件觸發時,會不斷設置計時器。然後計時器不會有機會打勾,直到調整大小結束,並在那一刻做一次處理。
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();
}
void _resizeTimer_Tick(object sender, EventArgs e)
{
_resizeTimer.IsEnabled = false;
//Do end of resize processing
}
.NET的反應式擴展爲處理標準事件模式提供了一些非常酷的功能,包括能夠節制事件。我在處理大小改變的事件時遇到了類似的問題,雖然解決方案仍然有些「黑客」,但我認爲Reactive Extensions提供了一種更加優雅的實現方式。下面是我的實現:
IObservable<SizeChangedEventArgs> ObservableSizeChanges = Observable
.FromEventPattern<SizeChangedEventArgs>(this, "SizeChanged")
.Select(x => x.EventArgs)
.Throttle(TimeSpan.FromMilliseconds(200));
IDisposable SizeChangedSubscription = ObservableSizeChanges
.ObserveOn(SynchronizationContext.Current)
.Subscribe(x => {
Size_Changed(x);
});
這將有效地節流SizeChanged
事件,使得您的SIZE_CHANGED方法(在這裏您可以執行自定義代碼)不會,直到200毫秒內執行(或但是長期要等待)已沒有通過另一個SizeChanged
事件被解僱。
private void Size_Changed(SizeChangedEventArgs e) {
// custom code for dealing with end of size changed here
}
真高雅! – MuiBienCarlota 2014-01-28 12:17:43
您可以準確檢測WPF窗口調整大小何時結束,並且您不需要計時器。本機窗口收到WM_EXITSIZEMOVE
消息,當用戶在窗口末尾釋放鼠標左鍵時調整大小或移動操作。一個WPF窗口不會收到這個消息,所以我們需要連接一個WndProc
函數來接收它。我們可以使用HwndSource
和WindowInteropHelper
來獲得我們的窗口句柄。然後我們將鉤子添加到我們的WndProc
函數中。我們將盡一切窗口Loaded
事件(vb.net代碼):
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
現在,在我們的WndProc
,我們會聽取WM_EXITSIZEMOVE
消息:
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
請注意,函數應該返回IntPtr.Zero。此外,除了處理您感興趣的特定消息外,請勿在此功能中執行任何操作。
現在,WM_EXITSIZEMOVE
也在移動操作結束時發送,我們只對調整大小感興趣。有幾種方法可以確定這是調整操作的結束。我通過收聽WM_SIZING
消息(在調整大小期間多次發送)並結合標記來完成此操作。整個解決方案是這樣的:
(注意:不要混淆代碼在這裏強調,導致其錯誤的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
就是這樣。
非常感謝您的提示!有計時器的解決方案非常糟糕.. – 2016-07-13 13:38:09
我認爲我們應該處理'WM_ENTERSIZEMOVE'而不是'WM_SIZING'。 – yumetodo 2017-09-28 11:47:12
- 1. 捕捉窗口調整大小
- 2. 如何在調整窗口大小時調整圖像大小?
- 3. 如何調整屏幕窗口大小?
- 4. 如何在窗口調整大小
- 5. 如何調整窗口大小
- 6. 如何調整GLUT窗口的大小?
- 7. 如何在隱藏窗口小部件後調整窗口大小,同時仍允許調整窗口大小?
- 8. 如何在窗口中調整窗口小部件的大小
- 9. 調整窗口大小Jquery
- 10. whiptail - 窗口大小調整
- 11. jQuery窗口調整大小
- 12. 調整窗口大小
- 13. 父窗口調整大小?
- 14. 而調整窗口大小
- 15. 調整窗口大小
- 16. 當調整窗口大小
- 17. Python窗口調整大小
- 18. Textarea調整窗口大小
- 19. 調整窗口大小C#
- 20. 調整窗口大小html
- 21. 調整窗口大小
- 22. jQuery窗口大小調整
- 23. 調整Windroy窗口大小
- 24. NSAlert調整窗口大小
- 25. SDL調整窗口大小
- 26. 調整大小窗口NicEditor
- 27. jquery窗口調整大小
- 28. NSOpenGLView調整窗口大小
- 29. 調整窗口大小窗口控件
- 30. 初始窗口大小/調整大小
Form.ResizeBegin/End在Winforms中。通知仍然存在,但在WPF中被忽略。前進兩步,退一步。 – 2010-12-17 21:46:05
@Martin,請解釋一下爲什麼你把_resizeTimer。IsEnabled = true;在開始之前?這對我來說看起來沒有意義。 – 2015-05-11 07:24:36
我喜歡這種機制,因爲它允許在用戶暫停調整大小時進行一些處理。有用戶調整大小時需要重新佈局畫布的情況。當用戶停止移動鼠標(但不釋放它)時,通過這種計時器方法,可以執行重新佈局,並且可以看到新尺寸的影響。 我的測試團隊喜歡它,而不是以前 - 重新佈局只發生在鼠標發佈時,即WM_EXITSIZEMOVE方法。 我確實將計時器時間間隔設置爲200ms,而不是此示例代碼中使用的1500值。 – pjm 2017-11-25 18:11:34