用P/Invoke訪問native API的問題 - RECT不等于System.Drawing.Rectangle。

(華版)

在昨晚我將以前编冩的某一個PocketPC應用程序(用Native API)换去.NET Compact Framework平台;因為以前只有Native API,所以就碰上一點點問題。。。但總算是迎刃而解!而以下是一點點地收獲和大家分享。

昨晚我下載了PaulYao编冩的API Explorer來找我所需要的Native API聲明方法。刚巧我就需要此GetWindowRect的聲明方法,而問題就是出現在GetWindowRect此API的聲明方法:
 


  

<DllImport("user32.dll")> _
Public Function GetWindowRect( _
   
ByVal hWnd As IntPtr _
   , 
ByRef lpRect As System.Drawing.Rectangle _
   ) 
As Integer
End Function

其實應該是以下的聲明方法才對:

<StructLayout(LayoutKind.Sequential)> _
Public Structure RECT
   
Public left As Integer
   
Public top As Integer
   
Public right As Integer
   
Public bottom As Integer
End Structure


<DllImport("user32.dll")> _
Public Function GetWindowRect( _
   
ByVal hWnd As IntPtr _
   , 
ByRef lpRect As RECT _
   ) 
As Integer
End Function

只是這样的一個錯誤。。。好攘我調試了好幾個小時也摸不凊到底出錯在那里。。。直到今天早上才發覺此API聲明有問題。因為前者把原有的RECT换去System.Drawing.Rectangle。而刚巧System.Drawing.Rectangle的structure size是大過RECT;所以前者是不會有异常錯誤(Exception Error)發生。但就返回一些不正确的數據。

  

闗于進一步去感受两者的區别,我就编冩了一個小小的程序來做個实验。從圖片里我們可以看到用System.Drawing.Rectangle所得到的數據跟用RECT所得到的數據是不一样。此外,我也用Form object里的Top, Left, Right和Bottom的值數來做對比;然而得到的數據就和RECT的一模一样。除了用程序來就証,我也用了Spy++(圖)來做另一項就証;這也証明了用RECT所得到的數據是正确而不是System.Drawing.Rectangle。

  

除此之外,我也發覺當聲明Native API時要特别留意ANSI和UNICODE的聲明方法。比如説用FindWindowW在WindowsXP平台去讀取某一個窗口的HWND是&H0;如果用FindWindowA就可讀取相闗的HWND值數。那是因為FindWindowW是用于UNICODE平台(PocketPC和WindowsCE)。

<DllImport("user32.dll")> _
Public Function FindWindowA( _
   
ByVal lpClassName As String _
   , 
ByVal lpWindowName As String _
   ) 
As IntPtr
End Function


<DllImport("user32.dll")> _
Public Function FindWindowW( _
   
ByVal lpClassName As String _
   , 
ByVal lpWindowName As String _
   ) 
As IntPtr
End Function

就在解决了我得問題。。。同時也發現了一個討論有闗P/Invoke的網頁www.pinvoke.net和一個纇似VB6.0 ApiViewer的開發工具ApiExplorer。如果你是Win32API的爱好者,就不能錯過這两样好的東西哦。

點撃下載代碼

posted on 2005-03-15 16:42  克仔  阅读(1416)  评论(2编辑  收藏  举报