@@ -4536,9 +4536,39 @@ private bool EquivalentKeys(object[] newKey, object[] oldKey, bool fCheckInts)
45364536 return true ;
45374537 }
45384538
4539- private const int WM_MOUSEWHEEL = 0x020A ;
45404539 private static readonly WheelRedirector s_wheelRedirector = new WheelRedirector ( ) ;
45414540
4541+ internal static int GetWheelScrollPixels ( DataTree dataTree , int delta )
4542+ {
4543+ if ( delta == 0 )
4544+ return 0 ;
4545+
4546+ int scrollLines = SystemInformation . MouseWheelScrollLines ;
4547+ if ( scrollLines == 0 )
4548+ return 0 ;
4549+
4550+ if ( scrollLines == int . MaxValue )
4551+ return Math . Sign ( delta ) * dataTree . ClientRectangle . Height ;
4552+
4553+ double linesToScroll = ( double ) delta / SystemInformation . MouseWheelScrollDelta * scrollLines ;
4554+ return ( int ) Math . Round ( linesToScroll * dataTree . Font . Height , MidpointRounding . AwayFromZero ) ;
4555+ }
4556+
4557+ internal static bool TryGetWheelScrollPosition ( DataTree dataTree , int delta , out int newY )
4558+ {
4559+ int currentY = - dataTree . AutoScrollPosition . Y ;
4560+ int maxScroll = Math . Max ( 0 ,
4561+ dataTree . AutoScrollMinSize . Height - dataTree . ClientRectangle . Height ) ;
4562+ int pixelDelta = GetWheelScrollPixels ( dataTree , delta ) ;
4563+ newY = Math . Max ( 0 , Math . Min ( currentY - pixelDelta , maxScroll ) ) ;
4564+ return newY != currentY ;
4565+ }
4566+
4567+ internal static bool CanRedirectWheelMessage ( DataTree dataTree )
4568+ {
4569+ return dataTree . IsHandleCreated && ! dataTree . IsDisposed && dataTree . Visible ;
4570+ }
4571+
45424572 /// <summary>
45434573 /// Application-level message filter that intercepts WM_MOUSEWHEEL messages
45444574 /// and scrolls the DataTree when the cursor is over its client area.
@@ -4549,12 +4579,13 @@ private bool EquivalentKeys(object[] newKey, object[] oldKey, bool fCheckInts)
45494579 /// </summary>
45504580 private sealed class WheelRedirector : IMessageFilter
45514581 {
4552- private readonly List < DataTree > m_dataTrees = new List < DataTree > ( ) ;
4582+ private readonly HashSet < DataTree > m_dataTrees = new HashSet < DataTree > ( ) ;
45534583 private bool m_installed ;
45544584
45554585 public void Register ( DataTree dataTree )
45564586 {
4557- m_dataTrees . Add ( dataTree ) ;
4587+ if ( ! m_dataTrees . Add ( dataTree ) )
4588+ return ;
45584589 if ( ! m_installed )
45594590 {
45604591 Application . AddMessageFilter ( this ) ;
@@ -4564,7 +4595,9 @@ public void Register(DataTree dataTree)
45644595
45654596 public void Unregister ( DataTree dataTree )
45664597 {
4567- m_dataTrees . Remove ( dataTree ) ;
4598+ if ( ! m_dataTrees . Remove ( dataTree ) )
4599+ return ;
4600+
45684601 if ( m_dataTrees . Count == 0 && m_installed )
45694602 {
45704603 Application . RemoveMessageFilter ( this ) ;
@@ -4574,28 +4607,28 @@ public void Unregister(DataTree dataTree)
45744607
45754608 public bool PreFilterMessage ( ref Message m )
45764609 {
4577- if ( m . Msg != WM_MOUSEWHEEL )
4610+ if ( m . Msg != ( int ) Win32 . WinMsgs . WM_MOUSEWHEEL )
45784611 return false ;
45794612
45804613 Point cursor = Cursor . Position ;
4581- for ( int i = 0 ; i < m_dataTrees . Count ; i ++ )
4614+ foreach ( var dataTree in m_dataTrees )
45824615 {
4583- var dataTree = m_dataTrees [ i ] ;
4584- if ( ! dataTree . IsHandleCreated || dataTree . IsDisposed )
4616+ if ( ! CanRedirectWheelMessage ( dataTree ) )
45854617 continue ;
45864618
45874619 Rectangle bounds = dataTree . RectangleToScreen ( dataTree . ClientRectangle ) ;
45884620 if ( ! bounds . Contains ( cursor ) )
45894621 continue ;
45904622
45914623 int delta = ( short ) ( ( long ) m . WParam >> 16 ) ;
4592- int currentY = - dataTree . AutoScrollPosition . Y ;
4593- int maxScroll = Math . Max ( 0 ,
4594- dataTree . AutoScrollMinSize . Height - dataTree . ClientRectangle . Height ) ;
4595- int newY = Math . Max ( 0 , Math . Min ( currentY - delta , maxScroll ) ) ;
4596- if ( newY != currentY )
4624+ int newY ;
4625+ if ( TryGetWheelScrollPosition ( dataTree , delta , out newY ) )
4626+ {
45974627 dataTree . AutoScrollPosition = new Point ( 0 , newY ) ;
4598- return true ;
4628+ return true ;
4629+ }
4630+
4631+ return false ;
45994632 }
46004633
46014634 return false ;
0 commit comments