当我滚动鼠标轮时,为什么我的WPF应用程序会崩溃?

8
当我滚动鼠标滚轮时,我的WPF应用程序有时会崩溃,并出现OverflowException。以下是堆栈跟踪的开头:
at System.Windows.Shell.WindowChromeWorker._HandleNCHitTest(WM uMsg, IntPtr wParam, IntPtr lParam, Boolean& handled)

我已经追踪到这个问题与 WindowChrome 相关 - 我甚至可以通过仅使用 WindowChrome 来重现它。但似乎它必须是全屏模式。这是怎么回事?有没有解决方法?


这个问题有一个解决方法在这里:https://developercommunity.visualstudio.com/content/problem/167357/overflow-exception-in-windowchrome.html - Ivan Golović
2个回答

14

这实际上是指向堆栈跟踪的类中存在的问题。微软在 WindowChromeWorker 中存在一个错误,会出现 OverflowException

我只观察到了与罗技鼠标相关的情况,但从其他地方看到,可能会发生在其他鼠标上。

唯一可用的解决方法是禁止全屏,并防止用户发送包含侧向滚动信息的消息。

我认为正在发生的是这样的:

//Overflow gets inlined to here. (In System.Windows.Shell.WindowChromeWorker.cs)
var mousePosScreen = new Point(Utility.GET_X_LPARAM(lParam), Utility.GET_Y_LPARAM(lParam));

//Which calls this (In Standard.Utility)
public static int GET_X_LPARAM(IntPtr lParam)
{
    return LOWORD(lParam.ToInt32());
}

//Unsafe cast and overflow happens here (In System.IntPtr)
public unsafe int ToInt32() {
    #if WIN32
        return (int)m_value;
    #else
        long l = (long)m_value;
        return checked((int)l); //Overflow actually occurs and is thrown from here.
    #endif
}

Standard.Utility中似乎有一个错误的假设,即lParam始终适合32位,在64位系统上某些鼠标驱动程序会违反该规定并将其写入那里。

WindowChromeWorker的参考源代码在这里


不错的发现!谢谢你的分享! - Lynn Crumbling
1
这个问题有一个解决方法在这里:https://developercommunity.visualstudio.com/content/problem/167357/overflow-exception-in-windowchrome.html - Ivan Golović

2

上面的评论中,Ivan Golović提供的解决方法需要在答案中包含,以便能够轻松地找到它,并在链接失效的情况下使用。

在HookProc中预处理消息,并在从lParam转换为int32时溢出时将其标记为已处理。

protected override void OnSourceInitialized( EventArgs e )
  {
     base.OnSourceInitialized( e );
     ( (HwndSource)PresentationSource.FromVisual( this ) ).AddHook( HookProc );
  }
  private IntPtr HookProc( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
  {
     if ( msg == 0x0084 /*WM_NCHITTEST*/ )
     {
        // This prevents a crash in WindowChromeWorker._HandleNCHitTest
        try
        {
           lParam.ToInt32();
        }
        catch ( OverflowException )
        {
           handled = true;
        }
     }
     return IntPtr.Zero;
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接