C# 什么会导致WM_nChitter LPRAM溢出32位整数?

C# 什么会导致WM_nChitter LPRAM溢出32位整数?,c#,wpf,winapi,C#,Wpf,Winapi,在什么条件下,消息的WM\u nchitest的lParam将是一个不适合32位整数的值 我们的一个客户看到他的64位计算机由于WPF应用程序中的未处理异常而崩溃,我很难找到原因。正在从WPF代码引发异常,如堆栈跟踪中所示: System.OverflowException: Arithmetic operation resulted in an overflow. at Microsoft.Windows.Shell.WindowChromeWorker._HandleNCHitTest

在什么条件下,消息的
WM\u nchitest
lParam
将是一个不适合32位整数的值

我们的一个客户看到他的64位计算机由于WPF应用程序中的未处理异常而崩溃,我很难找到原因。正在从WPF代码引发异常,如堆栈跟踪中所示:

System.OverflowException: Arithmetic operation resulted in an overflow.
   at Microsoft.Windows.Shell.WindowChromeWorker._HandleNCHitTest(WM uMsg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at Microsoft.Windows.Shell.WindowChromeWorker._WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.PublicHooksFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
有问题的方法
\u HandleNCHitTest
的来源是


我可以看到引发溢出异常的唯一方法是在将
lParam
转换为一个点的代码中,该点调用
IntPtr.ToInt32()。如果
lParam
不适合
Int32
,则引发此异常。然而,我想不出这种情况何时会发生。是什么导致了这种情况?

简短回答:使用自.NET 4.5以来集成的WindowChrome


长答案如果你不能切换到.NET4.5,这似乎对我有效,请参阅我对原始问题的评论。您永远无法确定,因为问题有时只在某些机器上出现,而不是在所有x64机器上:


我修改了WPFShell集成库v2的源代码。更改的行用
FWIW标记,当这两个都为真时,客户端会发生崩溃:1)他在嵌入程序的文本编辑器中快速上下滚动,2)程序窗口最大化。即使只有一个监视器也会发生崩溃。如果它没有最大化,它不会崩溃,并且除了滚动(他看到的)之外,没有其他操作会导致崩溃。你是否放弃了失败的可能性?不,我没有。你知道什么时候会发生吗?我不完全熟悉.NET的浮点模型。但是,再看一遍源代码,即使在高DPI显示器上,也不太可能出现溢出。我也有同样的问题。MSDN也帮不上我的忙:他们谈论“高阶字”并将字定义为16位,将WPARAM定义为IntPtr,但64位IntPtr上的高阶字是什么?我将更改相应的方法,以使用长时间的ToInt64(),并使用最低顺序的2个字(扔掉额外的4个字节)。也许这会有帮助…我在.NET4.7.2上也遇到了这个错误。使用内置的WindowChrome。查看referencesource,我发现Utilties.cs中的lParam.ToInt32()仍在使用,而不是64位方法。因此,我想仅仅切换到.Net v4.5或更高版本还不是解决方案(可能不再是了?),这里有一个解决问题的方法:
    private IntPtr _HandleSize(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
    {
        const int SIZE_MAXIMIZED = 2;

        // Force when maximized.
        // We can tell what's happening right now, but the Window doesn't yet know it's
        // maximized.  Not forcing this update will eventually cause the
        // default caption to be drawn.
        WindowState? state = null;
        if (wParam.ToInt64() == SIZE_MAXIMIZED)  <-----
        {
            state = WindowState.Maximized;
        }
        _UpdateSystemMenu(state);

        // Still let the default WndProc handle this.
        handled = false;
        return IntPtr.Zero;
    }
    [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
    public static int GET_X_LPARAM(IntPtr lParam)
    {
        return LOWORD(lParam.ToInt64());    <----
    }

    [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
    public static int GET_Y_LPARAM(IntPtr lParam)
    {
        return HIWORD(lParam.ToInt64());    <----
    }

    [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
    public static int HIWORD(long i)    <----
    {
        return (short)((i >> 16) & 0xFFFF);    <----
    }

    [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
    public static int LOWORD(long i)    <----
    {
        return (short)(i & 0xFFFF);
    }
    private IntPtr _WndProc(IntPtr hwnd, int uMsg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        WM message = (WM)uMsg;

        if (message == WM_TASKBARBUTTONCREATED)
        {
            _OnIsAttachedChanged(true);
            _isAttached = true;

            handled = false;
        }
        else
        {
            switch (message)
            {
                case WM.COMMAND:
                    if (Utility.HIWORD(wParam.ToInt64()) == THUMBBUTTON.THBN_CLICKED)  <-----
                    {
                        int index = Utility.LOWORD(wParam.ToInt64());   <----
                        ThumbButtonInfos[index].InvokeClick();
                        handled = true;
                    }
                    break;
                case WM.SIZE:
                    _UpdateThumbnailClipping(_isAttached);
                    handled = false;
                    break;
            }
        }

        return IntPtr.Zero;
    }