Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无法解释的OverflowException转换IntPtr,表示Int32的屏幕坐标_C#_.net_Winforms_Winapi_Wndproc - Fatal编程技术网

C# 无法解释的OverflowException转换IntPtr,表示Int32的屏幕坐标

C# 无法解释的OverflowException转换IntPtr,表示Int32的屏幕坐标,c#,.net,winforms,winapi,wndproc,C#,.net,Winforms,Winapi,Wndproc,我们有一个WinForms AnyCPU应用程序,其中供应商库控件偶尔会在运行多个监视器的64位用户框上引发以下异常: System.OverflowException: Arithmetic operation resulted in an overflow. at VendorLibraryName.VendorControl.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr

我们有一个WinForms AnyCPU应用程序,其中供应商库控件偶尔会在运行多个监视器的64位用户框上引发以下异常:

System.OverflowException: Arithmetic operation resulted in an overflow.
   at VendorLibraryName.VendorControl.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
我已经查看了供应商库控件的WndProc处理程序,看起来它可能会产生溢出的唯一代码是(我的注释-这是反编译的):

以下是转换和位旋转的实际IL:

IL_0092: ldarg.1
IL_0093: call instance native int [System.Windows.Forms]System.Windows.Forms.Message::get_LParam()

// As far as I can tell, this is the only instruction on which overflow could occur
IL_0098: call int32 [mscorlib]System.IntPtr::op_Explicit(native int)

IL_009d: ldc.i4 65535
IL_00a2: and
IL_00a3: ldarg.1

// Same thing here...
IL_00a4: call instance native int [System.Windows.Forms]System.Windows.Forms.Message::get_LParam()
IL_00a9: call int32 [mscorlib]System.IntPtr::op_Explicit(native int)

IL_00ae: ldc.i4.s 16
IL_00b0: shr
显然,由于64位进程中存在Message.LParam(一个IntPtr)到Int32的转换,因此该例程很容易出现溢出问题。事实上,这个例程是错误的,因为它不能正确处理负坐标-它看起来像是windows GET_X_LPARAM和GET_Y_PARAM宏到C的不正确端口

但是,我无法看到如何为NCHITTEST/NCMOUSEHOVER构造LPRAM,实际上,这会溢出Int32的范围。(我认为较低的16位由有符号的16位X坐标组成,其余的16位由符号扩展的16位Y坐标组成。如果我错了,请纠正我,因为这可能是一个严重的误解)

我无法使用许多不同的监视器配置和窗口位置在我的开发设备上重现异常


什么屏幕坐标可能会导致此处溢出?或者该块是否有任何其他方式会导致溢出?

我认为问题的关键在于“多个监视器”

从MSDN:

重要信息:不要使用LOWORD或HIWORD宏来提取x- 和光标位置的y坐标,因为这些宏返回 具有多个监视器的系统上的结果不正确。系统与 多个监视器可以有负的x坐标和y坐标以及LOWORD坐标 HIWORD将坐标视为无符号量

因为在CLR上,有符号数是用表示的,所以负数表示为“大”无符号数(其最高有效位为“1”);例如,-1是1111…1。因此,当强制转换为(有符号)32位整数时,会出现溢出

编辑: (免责声明:我没有多个监视器,因此有些猜测适用) 简言之:我的猜测是,你必须生成一个负的y坐标

假设坐标为(x:-1,y:-1)

作为短数字:x:0xFFFF,y:0xFFFF

打包在32位数字中:0xFFFF FFFF

现在,这里涉及到猜测:IntPtr没有符号扩展(你能用调试器试试吗?你需要一个负y坐标)。因此,它成为:

0x0000 0000 FFFF FFFF
或4294967295,该数字太大,无法将其转换为Int32

一般来说,任何负Y坐标都将以

000.(32 Zeros)..001 ...(other 31 digits) .. 0 

应该会出现问题(您是否尝试过将监视器一个叠在另一个上面?

我知道供应商例程中存在负坐标错误(如我所述)。但是,我使用负坐标(x和y)进行的测试都不会导致任何溢出异常-它们会导致坐标的错误解释。你能给我一些可能导致错误的负坐标吗?我想库中的错误是在应用掩码/移位之前转换为int。让我想想,如果有一种极端情况,坐标可能会产生非常大的数字。。或者,如果可以得出结论,没有任何值会导致溢出,那么您必须查看其他地方……我添加了我(受过教育的)猜测,并提供了一个示例我确实尝试模拟y坐标(包括告诉Windows我的监视器配置涉及垂直堆叠),这就是我注意到标志扩展发生的时候。无论如何,感谢您到目前为止的努力…因此我的猜测是错误的:)根据您的检查(数字是符号扩展的),我想说溢出是不可能的:Win32/BCL/Winforms正确地扩展了符号,然后供应商库将其缩减。这样,就不会出现超出有符号32位范围的数字。。您确定这是唯一可能导致溢出的点吗?即使您不知道参数溢出的原因,将IntPtr盲转换为Int32显然是库中的一个错误。微软只保证文档中的内容,不保证任何未文档化的内容。您应该与供应商联系以了解错误fix@Simon:没错。不过,该供应商在过去没有及时修复bug;所以我认为这需要时间。同时,我想确定到底是什么触发了生产中的异常,以便我们可以指导用户如何解决它。中期而言,我们可能会在应用程序代码中采取一些变通办法。不过首先,我需要一个复制品!嗯……这可能与虚拟桌面的大小有关吗?我能想到的唯一一件事就是适当的溢出…只是一个想法:你能安装一个全局IMessageFilter来避免进入那个函数,还是替换它?有点像这里描述的:@Simon:谢谢你。我仍然处在我希望能够重新开始的阶段;但你的建议看起来确实是一个不错的解决办法。
000.(32 Zeros)..001 ...(other 31 digits) .. 0