2015-10-22 51 views
2

在什麼情況下lParam對於消息WM_NCHITTEST是一個不符合32位整數的值?什麼會導致WM_NCHITTEST lParam溢出一個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一定程度上,它調用IntPtr.ToInt32()here的代碼。如果lParam不符合Int32,則會引發此例外情況。但是,當這種情況發生時,我無法想到這種情況。有什麼可以做到這一點?

+0

FWIW,出現客戶端崩潰時,這兩個是真實的:1)他在嵌入程序的文本編輯器中快速向上/向下滾動,2)程序窗口最大化。即使使用單臺顯示器也會發生崩潰。如果它沒有最大化,它不會崩潰,除了滾動(他看到)之外沒有其他動作導致崩潰。 – kcnygaard

+0

您是否放棄了[DpiHelper.DevicePixelsToLogical](http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Standard/DpiHelper.cs,c7b79208a4e6e6d0)失敗的可能性? – IInspectable

+0

不,我沒有。你知道什麼時候會發生嗎? – kcnygaard

回答

0

簡短回答:從.NET 4.5開始,使用WindowChrome集成。


長的答案,如果你不能切換到.NET 4.5,這似乎適用於我,請參閱我對原始問題的評論。你永遠無法確定,因爲這個問題有時只在有些機器上顯示,而不是在所有x64機器上顯示:

我修改了WPF Shell Integration Library 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; 
    } 
相關問題