C#調用Win32 api學習總結


windows api 手冊

 http://www.juliusun.com/class/docs/winapi/catalog.php

 

從.NET平台調用Win32 API

 

        Win32 API可以直接控制Microsoft Windows的核心,因為API(Application Programming Interface)本來就是微軟留給我們直接控制Windows的接口。

 

一.    基礎知識

        Win32 API是C語言(注意,不是C++語言,盡管C語言是C++語言的子集)函數集。

1. Win32 API函數放在哪里?

        Win32 API函數是Windows的核心,比如我們看到的窗體、按鈕、對話框什么的,都是依靠Win32函數“畫”在屏幕上的,由於這些控件(有時也稱組件)都用於用戶與Windows進行交互,所以控制這些控件的Win32 API函數稱為“用戶界面”函數(User Interface Win32 API),簡稱UI函數;還有一些函數,並不用於交互,比如管理當前系統正在運行的進程、硬件系統狀態的監視等等……這些函數只有一套,但是可以被所有的Windows程序調用(只要這個程序的權限足夠高),簡而言之,API是為程序所共享的。為了達到所有程序能共享一套API的目的,Windows采用了“動態鏈接庫”的辦法。之所以叫“動態鏈接庫”,是因為這樣的函數庫的調用方式是“隨用隨取”而不是像靜態鏈接庫那樣“用不用都要帶上”。

        

        Win32 API函數是放在Windows系統的核心庫文件中的,這些庫在硬盤里的存儲形式是.dll文件。我們常用到的dll文件是user32.dll和kernel32.dll兩個文件。

        這些dll文件是用C語言寫的,源代碼經C語言編譯器編譯之后,會以二進制可執行代碼形式存放在這些dll文件中。為了能讓程序使用這些函數,微軟在發布每個新的操作系統的時候,也會放出這個系統的SDK,目前最新的是Win2003 SP1 SDK,據說Vista的馬上就要放出來,而且已經把UI的API從核心庫中分離出去以提高系統的穩定性了。SDK里有一些C語言的頭文件(.h文件),這些文件里描述了核心dll文件里都有哪些Win32 API函數,在寫程序的時候,把這些.h文件用#include"....."指令包含進你的程序里,你就可以使用這些Win32 API了。

         C#語言也使用dll動態鏈接庫,不過這些dll都是.NET版本的,具有“自描述性”,也就是自己肚子里都有哪些函數都已經寫在自己的metadata里了,不用再附加一個.h文件來說明。現在,我們已經找到了問題的關鍵點:如何用.NET平台上的C#語言來調用Win32平台上的dll文件。答案非常簡單:使用DllImport特性。

二.  小試        

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;

,導入“運行時->交互服務”。喔~~~~運行時的交互服務不就是“動態鏈接”嗎?感謝Microsoft!

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完全一致!

從MSDN里摘出一張表來,是常用Win32數據類型與.NET平台數據類型的對應表:

Figure 2 Non-Pointer Data Types

 

 

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.

        有了這些東西,我們就能把一個Win32 API函數轉成C#函數了。還拿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的縮寫,說白了就是——字符串。所以,用

http://m.blog.csdn.net/article/details?id=50930221


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM