久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C#調(diào)用windows API的一些方法

 羊玉wngbx 2020-04-25

使用C#調(diào)用windows API(從其它地方總結(jié)來的,,以備查詢)

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

1.  直接調(diào)用從 DLL 導(dǎo)出的函數(shù)。

2.  調(diào)用 COM 對象上的接口方法

我主要討論從dll中導(dǎo)出函數(shù),,基本步驟如下:

1.使用 C# 關(guān)鍵字 static 和 extern 聲明方法,。

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

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

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

DWORD GetShortPathName(

LPCTSTR lpszLongPath,

LPTSTR lpszShortPath,

DWORD cchBuffer

);

2.查找對照表進行數(shù)據(jù)類型的轉(zhuǎn)換(出處:http://msdn.microsoft.com/msdnmag/issues/03/07/NET/default.aspx?fig=true  )Data

Win32 Types

Specification

CLR Type

char, INT8, SBYTE, CHARa€ 

8-bit signed integer

System.SByte

short, short int, INT16, SHORT

16-bit signed integer

System.Int16

int, long, long int, INT32, LONG32, BOOLa€ , INT

32-bit signed integer

System.Int32

__int64, INT64, LONGLONG

64-bit signed integer

System.Int64

unsigned char, UINT8, UCHARa€ , BYTE

8-bit unsigned integer

System.Byte

unsigned short, UINT16, USHORT, WORD, ATOM, WCHARa€ , __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

a€ 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.調(diào)用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(…)是可選項,,在這里即使沒有,程序也是可以調(diào)用此API了,。

說明:

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

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

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

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

二.背后的原理 ―― 知其所以然,,相關(guān)的知識

1.平臺調(diào)用詳原理

平臺調(diào)用依賴于元數(shù)據(jù)在運行時查找導(dǎo)出的函數(shù)并封送其參數(shù)。下圖顯示了這一過程,。

對非托管 DLL 函數(shù)的“平臺調(diào)用”調(diào)用

當“平臺調(diào)用”調(diào)用非托管函數(shù)時,,它將依次執(zhí)行以下操作:

查找包含該函數(shù)的 DLL。

將該 DLL 加載到內(nèi)存中,。

查找函數(shù)在內(nèi)存中的地址并將其參數(shù)推到堆棧上,,以封送所需的數(shù)據(jù)。

注意   只在第一次調(diào)用函數(shù)時,,才會查找和加載 DLL 并查找函數(shù)在內(nèi)存中的地址,。

將控制權(quán)轉(zhuǎn)移給非托管函數(shù)。

平臺調(diào)用會向托管調(diào)用方引發(fā)由非托管函數(shù)生成的異常,。

2.關(guān)于Attribute(屬性,,注意藍色字)

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

[DllImport] public class MyDllimportClass { ... }

有關(guān)更多信息,請參見 DllImportAttribute 類,。

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

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

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

[DllImport("user32.dll")]

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

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

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() {...}

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

3.MarshalAsAttribute 類

指示如何在托管代碼和非托管代碼之間封送數(shù)據(jù),??蓪⒃搶傩詰?yīng)用于參數(shù)、字段或返回值,。

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

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

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

下面,,就讓我們寫一個小程序,試一試如何用C#語言和DllImport特性來調(diào)用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", "水之真諦", 4);

Console.ReadLine();

return 0;

}

}

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

using System.Runtime.InteropServices;

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

3. 接下來就是我們的函數(shù)了,。在C#里調(diào)用Win32函數(shù)有這么幾個要點,。

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

第二:函數(shù)除了要有相應(yīng)的DllImport類修飾外,,還要聲明成public static extern類型的,。

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

常用Win32數(shù)據(jù)類型與.NET平臺數(shù)據(jù)類型的對應(yīng)表:

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函數(shù)為例(看剛才給出的函數(shù)表),,它的Win32原形如下:

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

函數(shù)名:MessageBox將保持不變。

返回值:int 將保持不變(無論是Win32還是C#,,int都是32位整數(shù))

參數(shù)表:H開頭意味著是Handle,,一般情況下Handld都是指針類型,Win32平臺的指針類型是用32位來存儲的,,所以在C#里正好對應(yīng)一個int整型,。不過,既然是指針,,就沒有什么正負之分,,32位都應(yīng)該用來保存數(shù)值——這樣一來,用uint(無符號32位整型)來對應(yīng)Win32的H類型更合理,。不過提醒大家一點,,int是受C#和.NET CLR雙重支持的,而uint只受C#支持而不受.NET CLR支持,,所以,,本例還是老老實實地使用了int型。(肚子餓了……再堅持堅持……)

至于LPCTSTR是Long Pointer to Constant String的縮寫,,說白了就是——字符串,。所以,用C#里的string類型就對了,。

修飾符:要求有相應(yīng)的DllImport和public static extern

經(jīng)過上面一番折騰,,Win32的MessageBox函數(shù)就包裝成C#可以調(diào)用的函數(shù)了:

[DllImport("User32.dll")]

public static extern int MessageBox(int h, string m, string c, int type);

第一個:彈出的MessageBox的父窗口是誰。本例中沒有,,所以是0,也就是“空指針”,。

第二個:MessageBox的內(nèi)容,。本例中是“Hello Win32 API”,。

第三個:MessageBox的標題。本例中用的是本人Blog的名字——水之真諦——請大家不要忘記,。

第四個:MessageBox上的按鈕是什么,,如果是0,那就只有一個OK,,MessageBox太短了,,你將看不全“水之真諦”四個字,于是偶改成了4,,這樣就有兩個按鈕了,。這些在MSDN的函數(shù)用法里都有。不過,,我還是非常推薦您閱讀一下本人的另一篇拙作《一個Win32程序的進化》 ,。

三. 真的有必要嗎?

.NET Framework是對Win32 API的良好封裝,,大部分Win32 API函數(shù)都已經(jīng)封裝在了.NET Framework類庫的各個類里了,。    

下面是個例子

那是在很久很久以前,我給一個公司寫程序用來控制用戶登錄,,在登錄之前,,用戶不能把鼠標移出登錄窗體,因為要控制鼠標,,所以我首先想起了調(diào)用Win32 API中與Cursor相關(guān)的函數(shù)來——于是不管三七二十一,、花了九牛二虎之力調(diào)用了Win32 API中的ClipCursor()這個函數(shù),效果還不錯,。

結(jié)果前兩天翻.NET Framework類庫的時候,,發(fā)現(xiàn)System.Windows.Forms.Cursor類的Clip屬性就是專門做這個用的!差點沒把鼻子氣歪了……請大家自己動手創(chuàng)建一個C#的Windows程序,,把下面的核心代碼貼到主窗體的雙擊事件里,,試一試。做這個例子的目的就是要告訴大家:1.對類庫的了解程序直接決定了你編程的效率和質(zhì)量——用類庫里的組件比我們“從輪子造起”要快得多,、安全得多,。2.不到萬不得已,不要去直接調(diào)Win32 API函數(shù)——那是不安全的,。

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#為例簡單介紹調(diào)用API的基本過程:  

動態(tài)鏈接庫函數(shù)聲明部分一般由下列兩部分組成,,一是函數(shù)名或索引號,,二是動態(tài)鏈接庫的文件名。  

譬如,,你想調(diào)用User32.DLL中的MessageBox函數(shù),,我們必須指明函數(shù)的名字MessageBoxA或MessageBoxW,以及庫名字User32.dll,我們知道Win32 API對每一個涉及字符串和字符的函數(shù)一般都存在兩個版本,,單字節(jié)字符的ANSI版本和雙字節(jié)字符的UNICODE版本,。

下面是一個調(diào)用API函數(shù)的例子:  

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

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

[DllImport("dllname", EntryPoint="Functionname")]  

[DllImport("dllname", EntryPoint="#123")]  

值得注意的是,,你必須在數(shù)字序號前加“#”  

下面是一個用MsgBox替換MessageBox名字的例子:  

using System.Runtime.InteropServices;  

[DllImport("user32.dll", EntryPoint="MessageBox")]  

public static extern int MsgBox(int hWnd, String text, String caption, uint type);  

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

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

布局選項  

描述  

LayoutKind.Automatic  

為了提高效率允許運行態(tài)對類型成員重新排序。  

注意:永遠不要使用這個選項來調(diào)用不受管轄的動態(tài)鏈接庫函數(shù),。  

LayoutKind.Explicit  

對每個域按照FieldOffset屬性對類型成員排序  

LayoutKind.Sequential  

對出現(xiàn)在受管轄類型定義地方的不受管轄內(nèi)存中的類型成員進行排序,。  

傳遞結(jié)構(gòu)成員  

下面的例子說明如何在受管轄代碼中定義一個點和矩形類型,并作為一個參數(shù)傳遞給User32.dll庫中的PtInRect函數(shù),,  

函數(shù)的不受管轄原型聲明如下:  

BOOL PtInRect(const RECT *lprc, POINT pt);  

注意你必須通過引用傳遞Rect結(jié)構(gòu)參數(shù),因為函數(shù)需要一個Rect的結(jié)構(gòu)指針,。  

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);  

類似你可以調(diào)用GetSystemInfo函數(shù)獲得系統(tǒng)信息:  

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);  

類成員的傳遞  

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

void GetSystemTime(SYSTEMTIME* SystemTime);  

不像傳值類型,類總是通過引用傳遞參數(shù).  

[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);  

回調(diào)函數(shù)的傳遞:  

從受管轄的代碼中調(diào)用大多數(shù)動態(tài)鏈接庫函數(shù),你只需創(chuàng)建一個受管轄的函數(shù)定義,,然后調(diào)用它即可,這個過程非常直接,。  

如果一個動態(tài)鏈接庫函數(shù)需要一個函數(shù)指針作為參數(shù),你還需要做以下幾步:  

首先,,你必須參考有關(guān)這個函數(shù)的文檔,,確定這個函數(shù)是否需要一個回調(diào);第二,,你必須在受管轄代碼中創(chuàng)建一個回調(diào)函數(shù),;最后,你可以把指向這個函數(shù)的指針作為一個參數(shù)創(chuàng)遞給DLL函數(shù),.

回調(diào)函數(shù)及其實現(xiàn):  

回調(diào)函數(shù)經(jīng)常用在任務(wù)需要重復(fù)執(zhí)行的場合,譬如用于枚舉函數(shù),譬如Win32 API 中的EnumFontFamilies(字體枚舉), EnumPrinters(打印機), EnumWindows (窗口枚舉)函數(shù). 下面以窗口枚舉為例,談?wù)勅绾瓮ㄟ^調(diào)用EnumWindow 函數(shù)遍歷系統(tǒng)中存在的所有窗口

分下面幾個步驟:  

1. 在實現(xiàn)調(diào)用前先參考函數(shù)的聲明  

BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARMAM IParam)  

顯然這個函數(shù)需要一個回調(diào)函數(shù)地址作為參數(shù).  

2. 創(chuàng)建一個受管轄的回調(diào)函數(shù),這個例子聲明為代表類型(delegate),也就是我們所說的回調(diào),它帶有兩個參數(shù)hwnd和lparam,第一個參數(shù)是一個窗口句柄,,第二個參數(shù)由應(yīng)用程序定義,,兩個參數(shù)均為整形。

當這個回調(diào)函數(shù)返回一個非零值時,,標示執(zhí)行成功,,零則暗示失敗,這個例子總是返回True值,,以便持續(xù)枚舉,。

3. 最后創(chuàng)建以代表對象(delegate),并把它作為一個參數(shù)傳遞給EnumWindows 函數(shù),,平臺會自動地 把代表轉(zhuǎn)化成函數(shù)能夠識別的回調(diào)格式,。

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;  

}  

}  

指針類型參數(shù)傳遞:  

在Windows API函數(shù)調(diào)用時,大部分函數(shù)采用指針傳遞參數(shù),,對一個結(jié)構(gòu)變量指針,,我們除了使用上面的類和結(jié)構(gòu)方法傳遞參數(shù)之外,我們有時還可以采用數(shù)組傳遞參數(shù),。

下面這個函數(shù)通過調(diào)用GetUserName獲得用戶名  

BOOL GetUserName(  

LPTSTR lpBuffer, // 用戶名緩沖區(qū)  

LPDWORD nSize // 存放緩沖區(qū)大小的地址指針  

);  

[DllImport("Advapi32.dll",  EntryPoint="GetComputerName",  ExactSpelling=false,  

SetLastError=true)]  

static extern bool GetComputerName ( [MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,  [MarshalAs(UnmanagedType.LPArray)] Int32[] nSize );  

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

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++之間類型的對應(yīng)

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轉(zhuǎn)換時,,需要加入前綴[MarshalAs(UnmanagedType.LPStr)]

LPDWORD   對應(yīng)于  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

[In] ref

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 操作系統(tǒng)上為 32 位,,在 64 位 Windows 操作系統(tǒng)上為 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.

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多