什么会导致 WM_NCHITTEST lParam 溢出 32 位整数?
Posted
技术标签:
【中文标题】什么会导致 WM_NCHITTEST lParam 溢出 32 位整数?【英文标题】:What would cause WM_NCHITTEST lParam to overflow a 32-bit integer? 【发布时间】:2016-01-22 02:47:52 【问题描述】:在什么情况下lParam
for message WM_NCHITTEST
是一个不适合 32 位整数的值?
由于我们的 WPF 应用程序中存在未处理的异常,我们的一位客户在他的 64 位计算机上看到崩溃,我很难找到原因。 从 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)
违规方法_HandleNCHitTest
的来源是here。
我可以看到引发溢出异常的唯一方法是将lParam
转换为Point 的代码,它调用IntPtr.ToInt32()
here。如果lParam
不适合Int32
,则会引发此异常。但是,我想不出这种情况可能发生的情况。什么可以做到这一点?
【问题讨论】:
FWIW,当这两个都为真时,客户端会发生崩溃:1)他在嵌入程序的文本编辑器中快速向上/向下滚动,2)程序窗口最大化。即使使用单个显示器也会发生崩溃。如果它没有最大化,它不会崩溃,并且除了滚动(他见过)之外没有其他操作会导致崩溃。 你放弃了DpiHelper.DevicePixelsToLogical失败的可能性吗? 不,我没有。你知道什么时候会发生吗? 我并不完全精通 .NET 的浮点模型。不过,再次查看源代码似乎不太可能导致溢出,即使在高 DPI 显示器上也是如此。 我也有同样的问题。 MSDN 也没有帮助我:Tey 谈论“高位字”并将 WORD 定义为 16 位,将 WPARAM 定义为 IntPtr,但是 64 位 IntPtr 上的高位字是什么?我将更改相应的方法以花费很长时间,使用 ToInt64() 并取最低位的 2 个字(丢弃 4 个额外的字节)。也许这有帮助...... 【参考方案1】:简答:使用自 .NET 4.5 以来集成的 WindowChrome。
如果您不能切换到 .NET 4.5,请给出长答案,这似乎对我有用,请参阅我对原始问题的评论。你永远无法确定,因为问题有时只出现在某些机器上,而不是所有 x64 机器上:
我修改了 WPF Shell 集成库 v2 的源代码。更改的行在末尾标有<----
。
WindowChromeWorker.cs:
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;
Utilities.cs:
[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);
TaskbarItemInfo.cs:
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;
【讨论】:
我在 .Net 4.7.2 上也遇到了这个错误。使用内置的 WindowChrome。查看参考源,我看到 Utilties.cs 中的 lParam.ToInt32() 仍然使用,而不是 64 位方法。所以我想只是切换到 .Net v4.5 或更高版本还不是解决方案(也许不再是?) 这里有一个解决方法:developercommunity.visualstudio.com/content/problem/167357/…以上是关于什么会导致 WM_NCHITTEST lParam 溢出 32 位整数?的主要内容,如果未能解决你的问题,请参考以下文章
WM_NCHITTEST有21种取值,常用的有HTCAPTION,HTCLIENT,HTBORDER,HTSYSMENU,HTTRANSPARENT,罗列所有VCL里对其使用的情况
c语言里的LPARAM类型对应的c#里是啥类型呢? LPARAM到底是怎么样的一个类型啊?
WM_NCHITTEST有21种取值,常用的有HTCAPTION,HTCLIENT,HTBORDER,HTSYSMENU,HTTRANSPARENT,罗列所有VCL里对其使用的情况