程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#基礎知識 >> C#調用windows API的一些方法

C#調用windows API的一些方法

編輯:C#基礎知識

使用C#調用windows API

C#調用windows API也可以叫做C#如何直接調用非托管代碼,通常有2種方法:

1.  直接調用從 DLL 導出的函數。

2.  調用 COM 對象上的接口方法

我主要討論從dll中導出函數,基本步驟如下:

1.使用 C# 關鍵字 staticextern 聲明方法。

2.將 DllImport 屬性附加到該方法。DllImport 屬性允許您指定包含該方法的 DLL 的名稱。

3.如果需要,為方法的參數和返回值指定自定義封送處理信息,這將重寫 .NET Framework 的默認封送處理。

1.首先我們查詢MSDN找到GetShortPathName的原型定義

 

DWORD GetShortPathName(

  LPCTSTR lpszLongPath,

  LPTSTR lpszShortPath,

  DWORD cchBuffer

);

 

2.查找對照表進行數據類型的轉換 Data

Win32 Types

Specification

CLR Type

char, INT8, SBYTE, CHAR†

8-bit signed integer

System.SByte

short, short int, INT16, SHORT

16-bit signed integer

System.Int16

int, long, long int, INT32, LONG32, BOOL†, INT

32-bit signed integer

System.Int32

__int64, INT64, LONGLONG

64-bit signed integer

System.Int64

unsigned char, UINT8, UCHAR†, BYTE

8-bit unsigned integer

System.Byte

unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR†, __wchar_t

16-bit unsigned integer

System.UInt16

unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT

32-bit unsigned integer

System.UInt32

unsigned __int64, UINT64, DWORDLONG, ULONGLONG

64-bit unsigned integer

System.UInt64

float, FLOAT

Single-precision floating point

System.Single

double, long double, DOUBLE

Double-precision floating point

System.Double

†In Win32 this type is an integer with a specially assigned meaning; in contrast, the CLR provides a specific type devoted to this meaning.

 

 

 

 

 

3.調用GetShortPathName這個API,簡單的寫法如下(編譯通過的話),

using System;

using System.Runtime.InteropServices;

    public class MSSQL_ServerHandler

    {

        [DllImport("kernel32.dll")]

        public static extern int GetShortPathName

        (

            string path,

            StringBuilder shortPath,

            int shortPathLength

)

     }

而我們之前的例子:

using System;

using System.Runtime.InteropServices;

    public class MSSQL_ServerHandler

    {

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]

        public static extern int GetShortPathName

        (

            [MarshalAs(UnmanagedType.LPTStr)] string path,

            [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,

            int shortPathLength

)

     }

對比可知,其中DllImport ,static,extern基本上是必須有的,其他CharSet,MarshalAs(…)是可選項,在這裡即使沒有,程序也是可以調用此API了。

說明:

1.MSSQL_ServerHandler. GetShortPathName 方法用 staticextern 修飾符聲明並且具有 DllImport 屬性,該屬性使用默認名稱GetShortPathName 通知編譯器此實現來自kernel32.dll。若要對 C# 方法使用不同的名稱(如 getShort),則必須在 DllImport 屬性中使用 EntryPoint 選項,如下所示:

[DllImport("kernel32.dll", EntryPoint="getShort")]

2使用MarshalAs(UnmanagedType.LPTStr)保證了在任何平台上都會得到LPTStr,否則默認的方式會把從C#中的字符串作為BStr傳遞。

 

現在如果是僅含有簡單參數和返回值的WIN32 API,就都可以利用這種方法進行對照,簡單的改寫和調用了。

 

二.背後的原理 ―― 知其所以然,相關的知識

 1.平台調用詳原理

平台調用依賴於元數據在運行時查找導出的函數並封送其參數。下圖顯示了這一過程。

對非托管 DLL 函數的“平台調用”調用

 

 

 

當“平台調用”調用非托管函數時,它將依次執行以下操作:

查找包含該函數的 DLL。

將該 DLL 加載到內存中。

查找函數在內存中的地址並將其參數推到堆棧上,以封送所需的數據。

注意   只在第一次調用函數時,才會查找和加載 DLL 並查找函數在內存中的地址。

將控制權轉移給非托管函數。

平台調用會向托管調用方引發由非托管函數生成的異常。

 2.關於Attribute(屬性,注意藍色字)

屬性可以放置在幾乎所有聲明中(但特定的屬性可能限制它在其上有效的聲明類型)。在語法上,屬性的指定方法為:將括在方括號中的屬性名置於其適用的實體聲明之前。例如,具有 DllImport 屬性的類將聲明如下:

[DllImport] public class MyDllimportClass { ... }

有關更多信息,請參見 DllImportAttribute 類。

許多屬性都帶參數,而這些參數可以是定位(未命名)參數也可以是命名參數。任何定位參數都必須按特定順序指定並且不能省略,而命名參數是可選的且可以按任意順序指定。首先指定定位參數。例如,這三個屬性是等效的:

[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]

[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]

[DllImport("user32.dll")]

第一個參數(DLL 名稱)是定位參數並且總是第一個出現,其他參數為命名參數。在此例中,兩個命名參數都默認為假,因此它們可以省略(有關默認參數值的信息,請參見各個屬性的文檔)。

在一個聲明中可以放置多個屬性,可分開放置,也可放在同一組括號中:

bool AMethod([In][Out]ref double x);

bool AMethod([Out][In]ref double x);

bool AMethod([In,Out]ref double x);

某些屬性對於給定實體可以指定多次。此類可多次使用的屬性的一個示例是 Conditional:

[Conditional("DEBUG"), Conditional("TEST1")] void TraceMethod() {...}

注意   根據約定,所有屬性名稱都以單詞“Attribute”結束,以便將它們與 .NET Framework 中的其他項區分。但是,在代碼中使用屬性時不需要指定屬性後綴。例如,[DllImport] 雖等效於 [DllImportAttribute],但 DllImportAttribute 才是該屬性在 .NET Framework 中的實際名稱。

3MarshalAsAttribute

指示如何在托管代碼和非托管代碼之間封送數據。可將該屬性應用於參數、字段或返回值。

該屬性為可選屬性,因為每個數據類型都有默認的封送處理行為。

大多數情況下,該屬性只是使用 UnmanagedType 枚舉標識非托管數據的格式。

例如,默認情況下,公共語言運行庫將字符串參數作為 BStr 封送到 COM 方法,但是可以通過制定MarshalAs屬性,將字符串作為 LPStr、LPWStr、LPTStr 或 BStr 封送到非托管代碼。某些 UnmanagedType 枚舉成員需要附加信息。

 

 

下面,就讓我們寫一個小程序,試一試如何用C#語言和DllImport特性來調用Win32 API。

using System;
using System.Runtime.InteropServices;
class Program
{
      [DllImport("User32.dll")]
      public static extern int MessageBox(int h, string m, string c, int type);

      static int Main()
      {
           MessageBox(0, "Hello Win32 API HoverTree", "何問起網", 4);
           Console.ReadLine();
           return 0;
      }
}


1. 要使用DllImport這個特性(特性也是一種類),必須使用這一句

using System.Runtime.InteropServices;


2. 然後我們就可以制造一個DllImport類的實例,並把這個實例綁定在我們要使用的函數上了。“特性類”這種類非常怪——制造類實例的時候不使用MyClass mc = new MyClass();這種形式,而是使用[特性類(參數列表)]這種形式;特性類不能獨立存在,一定要用作修飾其它目標上(本例是修飾後面的一個函數),不同的特性可以用來修飾類、函數、變量等等;特性類實例在被編譯的時候也不產生可執行代碼,而是被放進metadata裡以備檢索。總之,你記住特性類很怪就是了,想了解更多就查查MSDN,懶得查就先這麼記——不懂慣性定律不影響你學騎自行車。[DllImport("User32.dll")]是說我們要使用的Win32 API函數在User32.dll這個文件裡。問題又來了:我怎麼知道那麼多API函數都在哪個dll文件裡呢?這個你可以在MSDN裡查到,位置是Root->Win32 and COM Development->Development Guides->Windows API->Windows API->Windows API Reference->Functions by Category。打開這頁,你會看到有很多API的分類,API全在這裡了。打開一個分類,比如Dialog Box,Functions,你會看到很多具體的函數,其中就有上面用到的MessageBox函數,點擊進入。你將打開MessageBox的詳細解釋和具體用法。它的名字、返回值、參數類型盡收眼底、一覽無余!而且很練英文哦~~~~在這一頁的底部,你可以看到一個小表格,裡面有一項“Minimum DLL Version   user32.dll”就是說這個函數在user32.dll裡。
3. 接下來就是我們的函數了。在C#裡調用Win32函數有這麼幾個要點。

第一:名字要與Win32 API的完全一樣。

第二:函數除了要有相應的DllImport類修飾外,還要聲明成public static extern類型的。

第三:也是最變態的一點,函數的返回值和參數類型要與Win32 API完全一致!

常用Win32數據類型與.NET平台數據類型的對應表:
 

Win32 Types

Specification

CLR Type

char, INT8, SBYTE, CHAR

8-bit signed integer

System.SByte

short, short int, INT16, SHORT

16-bit signed integer

System.Int16

int, long, long int, INT32, LONG32, BOOL, INT

32-bit signed integer

System.Int32

__int64, INT64, LONGLONG

64-bit signed integer

System.Int64

unsigned char, UINT8, UCHAR, BYTE

8-bit unsigned integer

System.Byte

unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR, __wchar_t

16-bit unsigned integer

System.UInt16

unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT

32-bit unsigned integer

System.UInt32

unsigned __int64, UINT64, DWORDLONG, ULONGLONG

64-bit unsigned integer

System.UInt64

float, FLOAT

Single-precision floating point

System.Single

double, long double, DOUBLE

Double-precision floating point

System.Double

In Win32 this type is an integer with a specially assigned meaning; in contrast, the CLR provides a specific type devoted to this meaning.

 

以MessageBox函數為例(看剛才給出的函數表),它的Win32原形如下:

int MessageBox(HWND hWnd,   LPCTSTR lpText,    LPCTSTR lpCaption,  UINT uType );

函數名:MessageBox將保持不變。
返回值:int 將保持不變(無論是Win32還是C#,int都是32位整數)
參數表:H開頭意味著是Handle,一般情況下Handld都是指針類型,Win32平台的指針類型是用32位來存儲的,所以在C#裡正好對應一個int整型。不過,既然是指針,就沒有什麼正負之分,32位都應該用來保存數值——這樣一來,用uint(無符號32位整型)來對應Win32的H類型更合理。不過提醒大家一點,int是受C#和.NET CLR雙重支持的,而uint只受C#支持而不受.NET CLR支持,所以,本例還是老老實實地使用了int型。(肚子餓了……再堅持堅持……)
至於LPCTSTR是Long Pointer to Constant String的縮寫,說白了就是——字符串。所以,用C#裡的string類型就對了。
修飾符:要求有相應的DllImport和public static extern

經過上面一番折騰,Win32的MessageBox函數就包裝成C#可以調用的函數了:

    [DllImport("User32.dll")]
    public static extern int MessageBox(int h, string m, string c, int type);

第一個:彈出的MessageBox的父窗口是誰。本例中沒有,所以是0,也就是“空指針”。
第二個:MessageBox的內容。本例中是“Hello Win32 API HoverTree”。
第三個:MessageBox的標題。本例中用的是本人Blog的名字——何問起網——請大家不要忘記。
第四個:MessageBox上的按鈕是什麼,如果是0,那就只有一個OK,MessageBox太短了,你將看不全“何問起網”四個字,於是偶改成了4,這樣就有兩個按鈕了。這些在MSDN的函數用法裡都有。不過,我還是非常推薦您閱讀一下本人的另一篇拙作《一個Win32程序的進化》 。
     
三. 真的有必要嗎?
        .NET Framework是對Win32 API的良好封裝,大部分Win32 API函數都已經封裝在了.NET Framework類庫的各個類裡了。    

下面是個例子

        那是在很久很久以前,我給一個公司寫程序用來控制用戶登錄,在登錄之前,用戶不能把鼠標移出登錄窗體,因為要控制鼠標,所以我首先想起了調用Win32 API中與Cursor相關的函數來——於是不管三七二十一、花了九牛二虎之力調用了Win32 API中的ClipCursor()這個函數,效果還不錯。
        結果前兩天翻.NET Framework類庫的時候,發現System.Windows.Forms.Cursor類的Clip屬性就是專門做這個用的!差點沒把鼻子氣歪了……請大家自己動手創建一個C#的Windows程序,把下面的核心代碼貼到主窗體的雙擊事件裡,試一試。做這個例子的目的就是要告訴大家:1.對類庫的了解程序直接決定了你編程的效率和質量——用類庫裡的組件比我們從輪子造起要快得多、安全得多。2.不到萬不得已,不要去直接調Win32 API函數——那是不安全的。

Rectangle r = new Rectangle(this.Left, this.Top, this.Width, this.Height);
System.Windows.Forms.Cursor.Clip = r;

最後,大家一定非常想知道,.NET Framework都為我們封裝好了哪些Win32 API,OK,MSDN裡有一篇文章,專門列出了這些。文章的名字是《Microsoft Win32 to Microsoft .NET Framework API Map》  

 

 
下面以C#為例簡單介紹調用API的基本過程:  
 
  動態鏈接庫函數聲明部分一般由下列兩部分組成,一是函數名或索引號,二是動態鏈接庫的文件名。  
  譬如,你想調用User32.DLL中的MessageBox函數,我們必須指明函數的名字MessageBoxA或MessageBoxW,以及庫名字User32.dll,我們知道Win32 API對每一個涉及字符串和字符的函數一般都存在兩個版本,單字節字符的ANSI版本和雙字節字符的UNICODE版本。

  下面是一個調用API函數的例子:  
[DllImport("KERNEL32.DLL", EntryPoint="MoveFileW", SetLastError=true,  
CharSet=CharSet.Unicode, ExactSpelling=true,  
CallingConvention=CallingConvention.StdCall)]  
public static extern bool MoveFile(String src, String dst);  

  其中入口點EntryPoint標識函數在動態鏈接庫的入口位置,在一個受管轄的工程中,目標函數的原始名字和序號入口點不僅標識一個跨越互操作界限的函數。而且,你還可以把這個入口點映射為一個不同的名字,也就是對函數進行重命名。重命名可以給調用函數帶來種種便利,通過重命名,一方面我們不用為函數的大小寫傷透腦筋,同時它也可以保證與已有的命名規則保持一致,允許帶有不同參數類型的函數共存,更重要的是它簡化了對ANSI和Unicode版本的調用。CharSet用於標識函數調用所采用的是Unicode或是ANSI版本,ExactSpelling=false將告訴編譯器,讓編譯器決定使用Unicode或者是Ansi版本。其它的參數請參考MSDN在線幫助.

在C#中,你可以在EntryPoint域通過名字和序號聲明一個動態鏈接庫函數,如果在方法定義中使用的函數名與DLL入口點相同,你不需要在EntryPoint域顯示聲明函數。否則,你必須使用下列屬性格式指示一個名字和序號。

[DllImport("dllname", EntryPoint="Functionname")]  
[DllImport("dllname", EntryPoint="#123")]  
值得注意的是,你必須在數字序號前加“#”  
下面是一個用MsgBox替換MessageBox名字的例子:  

using System.Runtime.InteropServices;  

[DllImport("user32.dll", EntryPoint="MessageBox")]  
public static extern int MsgBox(int hWnd, String text, String caption, uint type);  


許多受管轄的動態鏈接庫函數期望你能夠傳遞一個復雜的參數類型給函數,譬如一個用戶定義的結構類型成員或者受管轄代碼定義的一個類成員,這時你必須提供額外的信息格式化這個類型,以保持參數原有的布局和對齊。

C#提供了一個StructLayoutAttribute類,通過它你可以定義自己的格式化類型,在受管轄代碼中,格式化類型是一個用StructLayoutAttribute說明的結構或類成員,通過它能夠保證其內部成員預期的布局信息。布局的選項共有三種:

布局選項  
描述  
LayoutKind.Automatic  
為了提高效率允許運行態對類型成員重新排序。  
注意:永遠不要使用這個選項來調用不受管轄的動態鏈接庫函數。  
LayoutKind.Explicit  
對每個域按照FieldOffset屬性對類型成員排序  
LayoutKind.Sequential  
對出現在受管轄類型定義地方的不受管轄內存中的類型成員進行排序。  
傳遞結構成員  
下面的例子說明如何在受管轄代碼中定義一個點和矩形類型,並作為一個參數傳遞給User32.dll庫中的PtInRect函數,  
函數的不受管轄原型聲明如下:  
BOOL PtInRect(const RECT *lprc, POINT pt);  
注意你必須通過引用傳遞Rect結構參數,因為函數需要一個Rect的結構指針。  
using System.Runtime.InteropServices;  

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

[StructLayout(LayoutKind.Explicit]  
public struct Rect {  
[FieldOffset(0)] public int left;  
[FieldOffset(4)] public int top;  
[FieldOffset(8)] public int right;  
[FieldOffset(12)] public int bottom;  
}  

[DllImport("User32.dll")]  
public static extern Bool PtInRect(ref Rect r, Point p);  
  
類似你可以調用GetSystemInfo函數獲得系統信息:  


 using System.Runtime.InteropServices;  
[StructLayout(LayoutKind.Sequential)]  
public struct SYSTEM_INFO {  
public uint dwOemId;  
public uint dwPageSize;  
public uint lpMinimumApplicationAddress;  
public uint lpMaximumApplicationAddress;  
public uint dwActiveProcessorMask;  
public uint dwNumberOfProcessors;  
public uint dwProcessorType;  
public uint dwAllocationGranularity;  
public uint dwProcessorLevel;  
public uint dwProcessorRevision;  
}  


[DllImport("kernel32")]  
static extern void GetSystemInfo(ref SYSTEM_INFO pSI);  

SYSTEM_INFO pSI = new SYSTEM_INFO();  
GetSystemInfo(ref pSI);  

類成員的傳遞  
同樣只要類具有一個固定的類成員布局,你也可以傳遞一個類成員給一個不受管轄的動態鏈接庫函數,下面的例子主要說明如何傳遞一個sequential順序定義的MySystemTime類給User32.dll的GetSystemTime函數, 函數用C/C++調用規范如下:

void GetSystemTime(SYSTEMTIME* SystemTime);  
不像傳值類型,類總是通過引用傳遞參數.  
 

[StructLayout(LayoutKind.Sequential)]  
public class MySystemTime {  
public ushort wYear;  
public ushort wMonth;  
public ushort wDayOfWeek;  
public ushort wDay;  
public ushort wHour;  
public ushort wMinute;  
public ushort wSecond;  
public ushort wMilliseconds;  
}  

 

[DllImport("User32.dll")]  
public static extern void GetSystemTime(MySystemTime st);  

 

回調函數的傳遞:  
從受管轄的代碼中調用大多數動態鏈接庫函數,你只需創建一個受管轄的函數定義,然後調用它即可,這個過程非常直接。  
如果一個動態鏈接庫函數需要一個函數指針作為參數,你還需要做以下幾步:  
首先,你必須參考有關這個函數的文檔,確定這個函數是否需要一個回調;第二,你必須在受管轄代碼中創建一個回調函數;最後,你可以把指向這個函數的指針作為一個參數創遞給DLL函數,.

回調函數及其實現:  
回調函數經常用在任務需要重復執行的場合,譬如用於枚舉函數,譬如Win32 API 中的EnumFontFamilies(字體枚舉), EnumPrinters(打印機), EnumWindows (窗口枚舉)函數. 下面以窗口枚舉為例,談談如何通過調用EnumWindow 函數遍歷系統中存在的所有窗口

分下面幾個步驟:  
1. 在實現調用前先參考函數的聲明  


BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARMAM IParam)  


顯然這個函數需要一個回調函數地址作為參數.  
2. 創建一個受管轄的回調函數,這個例子聲明為代表類型(delegate),也就是我們所說的回調,它帶有兩個參數hwnd和lparam,第一個參數是一個窗口句柄,第二個參數由應用程序定義,兩個參數均為整形。

當這個回調函數返回一個非零值時,標示執行成功,零則暗示失敗,這個例子總是返回True值,以便持續枚舉。


3. 最後創建以代表對象(delegate),並把它作為一個參數傳遞給EnumWindows 函數,平台會自動地 把代表轉化成函數能夠識別的回調格式。

using System;  
using System.Runtime.InteropServices;  

public delegate bool CallBack(int hwnd, int lParam);  

public class EnumReportApp {  

[DllImport("user32")]  
public static extern int EnumWindows(CallBack x, int y);  

public static void Main()  
{  
   CallBack myCallBack = new CallBack(EnumReportApp.Report);  
   EnumWindows(myCallBack, 0);  
}  

public static bool Report(int hwnd, int lParam) {  
    Console.Write("窗口句柄為");  
    Console.WriteLine(hwnd);  
    return true;  
}  
}  
指針類型參數傳遞:  
  在Windows API函數調用時,大部分函數采用指針傳遞參數,對一個結構變量指針,我們除了使用上面的類和結構方法傳遞參數之外,我們有時還可以采用數組傳遞參數。

  下面這個函數通過調用GetUserName獲得用戶名  

BOOL GetUserName(  
    LPTSTR lpBuffer, // 用戶名緩沖區  
    LPDWORD nSize // 存放緩沖區大小的地址指針  
);  
    
[DllImport("Advapi32.dll",  EntryPoint="GetComputerName",  ExactSpelling=false,  
SetLastError=true)]  
static extern bool GetComputerName ( [MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,  [MarshalAs(UnmanagedType.LPArray)] Int32[] nSize );  


  這個函數接受兩個參數,char * 和int *,因為你必須分配一個字符串緩沖區以接受字符串指針,你可以使用String類代替這個參數類型,當然你還可以聲明一個字節數組傳遞ANSI字符串,同樣你也可以聲明一個只有一個元素的長整型數組,使用數組名作為第二個參數。上面的函數可以調用如下:

byte[] str=new byte[20];  
Int32[] len=new Int32[1];  
len[0]=20;  
GetComputerName (str,len);  
MessageBox.Show(System.Text.Encoding.ASCII.GetString(str));  

 

 

 C#與C++之間類型的對應

Windows Data Type

.NET Data Type

BOOL, BOOLEAN

Boolean or Int32

BSTR

String

BYTE

Byte

CHAR

Char

DOUBLE

Double

DWORD

Int32 or UInt32

FLOAT

Single

HANDLE (and all other handle types, such as HFONT and HMENU)

IntPtr, UintPtr or HandleRef

HRESULT

Int32 or UInt32

INT

Int32

LANGID

Int16 or UInt16

LCID

Int32 or UInt32

LONG

Int32

LPARAM

IntPtr, UintPtr or Object

LPCSTR

String

LPCTSTR

String

LPCWSTR

String

LPSTR

String or StringBuilder*

LPTSTR

String or StringBuilder

LPWSTR

String or StringBuilder

LPVOID

IntPtr, UintPtr or Object

LRESULT

IntPtr

SAFEARRAY

.NET array type

SHORT

Int16

TCHAR

Char

UCHAR

SByte

UINT

Int32 or UInt32

ULONG

Int32 or UInt32

VARIANT

Object

VARIANT_BOOL

Boolean

WCHAR

Char

WORD

Int16 or UInt16

WPARAM

IntPtr, UintPtr or Object

 

 

另: 在進行string轉換時,需要加入前綴[MarshalAs(UnmanagedType.LPStr)]

LPDWORD   對應於  ref int

C/C++

C#

HANDLE, LPDWORD, LPVOID, void*

IntPtr

LPCTSTR, LPCTSTR, LPSTR, char*, const char*, Wchar_t*, LPWSTR

String [in], StringBuilder [in, out]

DWORD, unsigned long, Ulong

UInt32, [MarshalAs(UnmanagedType.U4)]

bool

bool

LP<struct>

[In] ref <struct>

SIZE_T

uint

LPDWORD

out uint

LPTSTR

[Out] StringBuilder

PULARGE_INTEGER

out ulong

WORD

uInt16

Byte, unsigned char

byte

Short

Int16

Long, int

Int32

float

single

double

double

NULL pointer

IntPtr.Zero

Uint

Uint32

 

Wtypes.h 中的非托管類型

非托管 C 語言類型

托管類名

說明

HANDLE

void*

System.IntPtr

在 32 位 Windows 操作系統上為 32 位,在 64 位 Windows 操作系統上為 64 位。

BYTE

unsigned char

System.Byte

8 位

SHORT

short

System.Int16

16 位

WORD

unsigned short

System.UInt16

16 位

INT

int

System.Int32

32 位

UINT

unsigned int

System.UInt32

32 位

LONG

long

System.Int32

32 位

BOOL

long

System.Int32

32 位

DWORD

unsigned long

System.UInt32

32 位

ULONG

unsigned long

System.UInt32

32 位

CHAR

char

System.Char

用 ANSI 修飾。

LPSTR

char*

System.String 或 System.Text.StringBuilder

用 ANSI 修飾。

LPCSTR

Const char*

System.String 或 System.Text.StringBuilder

用 ANSI 修飾。

LPWSTR

wchar_t*

System.String 或 System.Text.StringBuilder

用 Unicode 修飾。

LPCWSTR

Const wchar_t*

System.String 或 System.Text.StringBuilder

用 Unicode 修飾。

FLOAT

Float

System.Single

32 位

DOUBLE

Double

System.Double

64 位

 

BOOL=System.Int32
BOOLEAN=System.Int32
BYTE=System.UInt16
CHAR=System.Int16
COLORREF=System.UInt32
DWORD=System.UInt32
DWORD32=System.UInt32
DWORD64=System.UInt64
FLOAT=System.Float
HACCEL=System.IntPtr
HANDLE=System.IntPtr
HBITMAP=System.IntPtr
HBRUSH=System.IntPtr
HCONV=System.IntPtr
HCONVLIST=System.IntPtr
HCURSOR=System.IntPtr
HDC=System.IntPtr
HDDEDATA=System.IntPtr
HDESK=System.IntPtr
HDROP=System.IntPtr
HDWP=System.IntPtr
HENHMETAFILE=System.IntPtr
HFILE=System.IntPtr
HFONT=System.IntPtr
HGDIOBJ=System.IntPtr
HGLOBAL=System.IntPtr
HHOOK=System.IntPtr
HICON=System.IntPtr
HIMAGELIST=System.IntPtr
HIMC=System.IntPtr
HINSTANCE=System.IntPtr
HKEY=System.IntPtr
HLOCAL=System.IntPtr
HMENU=System.IntPtr
HMETAFILE=System.IntPtr
HMODULE=System.IntPtr
HMONITOR=System.IntPtr
HPALETTE=System.IntPtr
HPEN=System.IntPtr
HRGN=System.IntPtr
HRSRC=System.IntPtr
HSZ=System.IntPtr
HWINSTA=System.IntPtr
HWND=System.IntPtr
INT=System.Int32
INT32=System.Int32
INT64=System.Int64
LONG=System.Int32
LONG32=System.Int32
LONG64=System.Int64
LONGLONG=System.Int64
LPARAM=System.IntPtr
LPBOOL=System.Int16[]
LPBYTE=System.UInt16[]
LPCOLORREF=System.UInt32[]
LPCSTR=System.String
LPCTSTR=System.String
LPCVOID=System.UInt32
LPCWSTR=System.String
LPDWORD=System.UInt32[]
LPHANDLE=System.UInt32
LPINT=System.Int32[]
LPLONG=System.Int32[]
LPSTR=System.String
LPTSTR=System.String
LPVOID=System.UInt32
LPWORD=System.Int32[]
LPWSTR=System.String
LRESULT=System.IntPtr
PBOOL=System.Int16[]
PBOOLEAN=System.Int16[]
PBYTE=System.UInt16[]
PCHAR=System.Char[]
PCSTR=System.String
PCTSTR=System.String
PCWCH=System.UInt32
PCWSTR=System.UInt32
PDWORD=System.Int32[]
PFLOAT=System.Float[]
PHANDLE=System.UInt32
PHKEY=System.UInt32
PINT=System.Int32[]
PLCID=System.UInt32
PLONG=System.Int32[]
PLUID=System.UInt32
PSHORT=System.Int16[]
PSTR=System.String
PTBYTE=System.Char[]
PTCHAR=System.Char[]
PTSTR=System.String
PUCHAR=System.Char[]
PUINT=System.UInt32[]
PULONG=System.UInt32[]
PUSHORT=System.UInt16[]
PVOID=System.UInt32
PWCHAR=System.Char[]
PWORD=System.Int16[]
PWSTR=System.String
REGSAM=System.UInt32
SC_HANDLE=System.IntPtr
SC_LOCK=System.IntPtr
SHORT=System.Int16
SIZE_T=System.UInt32
SSIZE_=System.UInt32
TBYTE=System.Char
TCHAR=System.Char
UCHAR=System.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved