2011-07-05 162 views
2

我不習慣P/Invoke,但我應該聲明一些WinAPI函數來獲取或設置鍵盤佈局。我聲明的功能,如:C#P /調用鍵盤佈局和編譯器警告


[DllImport("user32.dll")] 
private static extern long LoadKeyboardLayout(
    string pwszKLID, // input locale identifier 
    uint Flags   // input locale identifier options 
    ); 

[DllImport("user32.dll")] 
private static extern long GetKeyboardLayoutName(
    StringBuilder pwszKLID //[out] string that receives the name of the locale identifier 
    ); 

但是,當我編譯這個(在C#WPF應用程序),我得到的警告:

CA1901 Microsoft.Portability 因爲它在你的代碼中聲明, P/Invoke 的返回類型在64位平臺上將爲4個字節寬。 這是不正確的,因爲這個API的實際本地聲明 表示它應該在64位平臺上有8個字節寬。 請參閱MSDN平臺SDK文檔以獲取幫助,以確定 應使用哪種數據類型而不是「long」。

和(我想這是不太受關注的鍵盤佈局的名字只是個數字的):

CA2101 Microsoft.Globalization 爲了降低安全風險,元帥參數「pwszKLID」爲Unicode,通過設置的DllImport .CharSet爲CharSet.Unicode,或者通過顯式封送參數爲UnmanagedType.LPWStr。如果您需要將此字符串編爲ANSI或系統相關,請明確指定MarshalAs,並設置BestFitMapping = false;爲了增加安全性,還要設置ThrowOnUnmappableChar = true。

我嘗試使用IntPtr的第一個警告,但這並不能解決問題。任何人都可以幫助我指出這些聲明的正確形式嗎? 謝謝!

回答

1

您可以嘗試使用以下聲明:

[DllImport("user32.dll", CharSet=CharSet.Unicode)] 
private static extern IntPtr LoadKeyboardLayout(
    string pwszKLID, // input locale identifier 
    uint Flags   // input locale identifier options 
    ); 

[DllImport("user32.dll", CharSet = CharSet.Unicode)] 
[return : MarshalAs(UnmanagedType.Bool)] 
private static extern bool GetKeyboardLayoutName(
    StringBuilder pwszKLID //[out] string that receives the name of the locale identifier 
    ); 

CharSet規範將清理CA2101。將兩種方法的退貨調整爲正確的退貨類型並在GetKeyboardLayoutName上添加MarshalAs以返回將清除CA1901。

+0

C#「布爾」的默認編組就是Windows BOOL。因此,MarshalAs不是必需的。 –

+0

@David,我原本是這樣離開它的,但隨着Naftis已經引發了警告,代碼分析開啓了,它確實爲我產生了一個警告。因此增加了MarshalAs。 –

0

LoadKeyboardLayout返回HKL,它實際上是void *。

 
typedef PVOID HANDLE; 
typedef HANDLE HKL; 

GetKeyboardLayoutName返回BOOL,它實際上是32位的int。所以,你需要定義 LoadKeyboardLayout返回類型爲IntPtr,並且GetKeyboardLayoutName返回類型爲int。

+0

感謝這工作的第一次警告!至於第二,我認爲我可以放心地忽略它...... – Naftis