2015-10-12 55 views
0

我有一個與結構聲明有關的問題,我結合使用Windows函數WindowFromPointGetCursorPos。當結構具有int字段時,代碼分析報告錯誤:CA1901:PInvokeDeclarationsShouldBePortable(CA1901 P/Invoke聲明應該是可移植的,因爲它在你的代碼中聲明,所以P/Invoke NativeMethods.WindowFromPoint(NativeMethods.POINTAPI)的參數'point' )當我將字段類型更改爲Int16時,不會返回錯誤,但函數GetCursorPos停止工作。如何聲明POINT結構以擺脫代碼分析錯誤?

我在Windows 8.1 x64上運行應用程序。是的功能和結構的特徵如下:

[DllImport("user32.dll")] 
internal static extern IntPtr WindowFromPoint(POINTAPI point); 

[StructLayout(LayoutKind.Sequential)] 
public struct POINTAPI 
{ 
    internal int x; 
    internal int y; 
} 

[DllImport("user32.dll")] 
internal static extern int GetCursorPos(out POINTAPI lpPoint); 

下面是什麼我試圖做一個總結:

  1. X和Y聲明爲int(如上) - - 應用程序正常工作,代碼分析顯示錯誤。
  2. X和y聲明爲Int16 ---調用函數GetCursorPos時,應用程序崩潰,代碼分析不會返回錯誤。
  3. X和y聲明爲Int32 ---應用程序正常工作,代碼分析顯示錯誤。
  4. X和y聲明爲Int64 ---函數WindowFromPoint返回意外結果,代碼分析顯示錯誤。

有沒有人知道如何讓應用程序工作,而沒有代碼分析錯誤(目前已被壓制)?

+1

如果您明確地將結構成員編組爲「UnmanagedType.I4」,分析警告是否會消失? – theB

+1

[文檔](https://msdn.microsoft.com/en-us/library/ms182284.aspx)說_Breaking - 如果P/Invoke在程序集外部可見。不中斷 - 如果P/Invoke在程序集外部是不可見的。那麼你可以使'POINTAPI'內部還是私人? – juharr

+0

@juharr由於'x'和'y'都是'internal',我懷疑答案是肯定的。 – Luaan

回答

2

那麼,Int16Int64失敗,因爲它們是錯誤的類型。本地聲明使用LONG,它的簽名是32位。所以intInt32都是正確的。

您的問題中的結構聲明正是我如何聲明這一點。但如果你願意的話,你也可以使用Int32

然而,WindowFromPoint是不尋常的。它接受POINT而不是POINT*這有點奇怪。我懷疑微軟的工程師很久以前就搞錯了,而且現在顯然不能改變它。

看起來這個不尋常的功能聲明WindowFromPoint實際上是混淆了代碼分析工具。但重要的是你的代碼工作。因此,請使用正確的代碼(如在此問題中的代碼中所示),並抑制僞代碼分析警告。