@@ -114,6 +114,12 @@ static void OnUnloaded(object? sender, RoutedEventArgs e)
114114 }
115115 }
116116
117+ static void RemoveHandlers ( ScrollViewer scrollViewer )
118+ {
119+ WeakEventManager < ScrollViewer , RoutedEventArgs > . RemoveHandler ( scrollViewer , nameof ( ScrollViewer . Loaded ) , OnLoaded ) ;
120+ WeakEventManager < ScrollViewer , RoutedEventArgs > . RemoveHandler ( scrollViewer , nameof ( ScrollViewer . Unloaded ) , OnUnloaded ) ;
121+ }
122+
117123 static void RemoveHook ( ScrollViewer scrollViewer )
118124 {
119125 if ( scrollViewer . GetValue ( HorizontalScrollHookProperty ) is HwndSourceHook hook &&
@@ -138,12 +144,20 @@ static void RegisterHook(ScrollViewer scrollViewer)
138144 IntPtr Hook ( IntPtr hwnd , int msg , IntPtr wParam , IntPtr lParam , ref bool handled )
139145 {
140146 const int WM_MOUSEHWHEEL = 0x020E ;
147+ const int WM_DESTROY = 0x0002 ;
148+ const int WM_NCDESTROY = 0x0082 ;
141149 switch ( msg )
142150 {
143151 case WM_MOUSEHWHEEL when scrollViewer . IsMouseOver :
144152 int tilt = ( short ) ( ( wParam . ToInt64 ( ) >> 16 ) & 0xFFFF ) ;
145153 scrollViewer . ScrollToHorizontalOffset ( scrollViewer . HorizontalOffset + tilt ) ;
146154 return ( IntPtr ) 1 ;
155+ case WM_DESTROY :
156+ case WM_NCDESTROY :
157+ RemoveHandlers ( scrollViewer ) ;
158+ var source = PresentationSource . FromVisual ( scrollViewer ) as HwndSource ;
159+ source ? . RemoveHook ( Hook ) ;
160+ break ;
147161 }
148162 return IntPtr . Zero ;
149163 }
@@ -196,6 +210,12 @@ static void OnUnloaded(object? sender, RoutedEventArgs e)
196210 }
197211 }
198212
213+ static void RemoveHandlers ( ScrollViewer scrollViewer )
214+ {
215+ WeakEventManager < ScrollViewer , RoutedEventArgs > . RemoveHandler ( scrollViewer , nameof ( ScrollViewer . Loaded ) , OnLoaded ) ;
216+ WeakEventManager < ScrollViewer , RoutedEventArgs > . RemoveHandler ( scrollViewer , nameof ( ScrollViewer . Unloaded ) , OnUnloaded ) ;
217+ }
218+
199219 static void RemoveHook ( ScrollViewer scrollViewer )
200220 {
201221 scrollViewer . RemoveHandler ( UIElement . MouseWheelEvent , ( RoutedEventHandler ) ScrollViewerOnMouseWheel ) ;
@@ -204,7 +224,28 @@ static void RemoveHook(ScrollViewer scrollViewer)
204224 static void RegisterHook ( ScrollViewer scrollViewer )
205225 {
206226 RemoveHook ( scrollViewer ) ;
207- scrollViewer . AddHandler ( UIElement . MouseWheelEvent , ( RoutedEventHandler ) ScrollViewerOnMouseWheel , true ) ;
227+ if ( PresentationSource . FromVisual ( scrollViewer ) is HwndSource source )
228+ {
229+ HwndSourceHook hook = Hook ;
230+ source . AddHook ( hook ) ;
231+ scrollViewer . AddHandler ( UIElement . MouseWheelEvent , ( RoutedEventHandler ) ScrollViewerOnMouseWheel , true ) ;
232+ }
233+
234+ IntPtr Hook ( IntPtr hwnd , int msg , IntPtr wParam , IntPtr lParam , ref bool handled )
235+ {
236+ const int WM_DESTROY = 0x0002 ;
237+ const int WM_NCDESTROY = 0x0082 ;
238+ switch ( msg )
239+ {
240+ case WM_DESTROY :
241+ case WM_NCDESTROY :
242+ RemoveHandlers ( scrollViewer ) ;
243+ var source = PresentationSource . FromVisual ( scrollViewer ) as HwndSource ;
244+ source ? . RemoveHook ( Hook ) ;
245+ break ;
246+ }
247+ return IntPtr . Zero ;
248+ }
208249 }
209250
210251 // This relay is only needed because the UIElement.AddHandler() has strict requirements for the signature of the passed Delegate
0 commit comments