在C 程式設計中使用Win32類庫

2021-05-22 12:47:50 字數 3020 閱讀 6549

在c#程式設計中使用win32類庫

**: csdnblog

c# 使用者經常提出兩個問題:「我為什麼要另外編寫**來使用內置於 windows 中的功能?在框架中為什麼沒有相應的內容可以為我完成這一任務?」當框架小組構建他們的 .net 部分時,他們評估了為使 .net 程式設計師可以使用 win32 而需要完成的工作,結果發現 win32 api 集非常龐大。他們沒有足夠的資源為所有 win32 api 編寫託管介面、加以測試並編寫文件,因此只能優先處理最重要的部分。許多常用操作都有託管介面,但是還有許多完整的 win32 部分沒有託管介面。

平台呼叫 (p/invoke) 是完成這一任務的最常用方法。要使用 p/invoke,您可以編寫乙個描述如何呼叫函式的原型,然後執行時將使用此資訊進行呼叫。另一種方法是使用 managed extensions to c++ 來包裝函式,這部分內容將在以後的專欄中介紹。

簡單示例

在第乙個示例中,我們將呼叫 beep() api 來發出聲音。首先,我需要為 beep() 編寫適當的定義。檢視 msdn 中的定義,我發現它具有以下原型:

bool beep(

dword dwfreq,   // 聲音頻率

dword dwduration  // 聲音持續時間

); 要用 c# 來編寫這一原型,需要將 win32 型別轉換成相應的 c# 型別。由於 dword 是 4 位元組的整數,因此我們可以使用 int 或 uint 作為 c# 對應型別。由於 int 是 cls 相容型別(可以用於所有 .net 語言),以此比 uint 更常用,並且在多數情況下,它們之間的區別並不重要。bool 型別與 bool 對應。現在我們可以用 c# 編寫以下原型:

public static extern bool beep(int frequency, int duration);

這是相當標準的定義,只不過我們使用了 extern 來指明該函式的實際**在別處。此原型將告訴執行時如何呼叫函式;現在我們需要告訴它在何處找到該函式。

我們需要回顧一下 msdn 中的**。在參考資訊中,我們發現 beep() 是在 kernel32.lib 中定義的。這意味著執行時**包含在 kernel32.dll 中。我們在原型中新增 dllimport 屬性將這一資訊告訴執行時:

[dllimport("kernel32.dll")]

這就是我們要做的全部工作。下面是乙個完整的示例,它生成的隨機聲音在二十世紀六十年代的科幻電影中很常見。

using system;

using system.runtime.interopservices;

namespace beep}}

} 它的聲響足以刺激任何聽者!由於 dllimport 允許您呼叫 win32 中的任何**,因此就有可能呼叫惡意**。所以您必須是完全受信任的使用者,執行時才能進行 p/invoke 呼叫。

列舉和常量

beep() 可用於發出任意聲音,但有時我們希望發出特定型別的聲音,因此我們改用 messagebeep()。msdn 給出了以下原型:

bool messagebeep(

uint utype // 聲音型別

); 這看起來很簡單,但是從注釋中可以發現兩個有趣的事實。

首先,utype 引數實際上接受一組預先定義的常量。

其次,可能的引數值包括 -1,這意味著儘管它被定義為 uint 型別,但 int 會更加適合。

對於 utype 引數,使用 enum 型別是合乎情理的。msdn 列出了已命名的常量,但沒有就具體值給出任何提示。由於這一點,我們需要檢視實際的 api。

如果您安裝了 visual studio? 和 c++,則 platform sdk 位於 /program files/microsoft visual studio .net/vc7/platformsdk/include 下。

為查詢這些常量,我在該目錄中執行了乙個 findstr。

findstr "mb_iconhand" *.h

它確定了常量位於 winuser.h 中,然後我使用這些常量來建立我的 enum 和原型:

public enum beeptype

[dllimport("user32.dll")]

public static extern bool messagebeep(beeptype beeptype);

現在我可以用下面的語句來呼叫它: messagebeep(beeptype.iconquestion);

處理結構

有時我需要確定我筆記本的電池狀況。win32 為此提供了電源管理函式。

搜尋 msdn 可以找到 getsystempowerstatus() 函式。

bool getsystempowerstatus(

lpsystem_power_status lpsystempowerstatus

); 

此函式包含指向某個結構的指標,我們尚未對此進行過處理。要處理結構,我們需要用 c# 定義結構。我們從非託管的定義開始:

typedef struct _system_power_status system_power_status, *lpsystem_power_status; 

然後,通過用 c# 型別代替 c 型別來得到 c# 版本。

struct systempowerstatus

這樣,就可以方便地編寫出 c# 原型:

[dllimport("kernel32.dll")]

public static extern bool getsystempowerstatus(

ref systempowerstatus systempowerstatus); 

在此原型中,我們用「ref」指明將傳遞結構指標而不是結構值。這是處理通過指標傳遞的結構的一般方法。

此函式執行良好,但是最好將 aclinestatus 和 batteryflag 字段定義為 enum:

enum aclinestatus: byte

enum batteryflag: byte

請注意,由於結構的字段是一些位元組,因此我們使用 byte 作為該 enum 的基本型別。

WIN32中使用GDI 入門

方法和我前面寫過的vs2013使用gdi 一樣 2 配置 專案 屬性 配置屬性 聯結器 輸入 附加依賴庫中新增 gdiplus.lib 3 新增標頭檔案,放在主函式標頭檔案中,這個位置隨意 include include gdiplus.h using namespace gdiplus pragm...

在Win32下使用OpenGL

1.win32程式的框架是winmain wndproc。winmain中建立視窗同時實現訊息迴圈,wndproc中實現的是訊息的處理。2.win32程式執行時的過程主要是1 建立視窗2 捕獲視窗中的訊息並處理 win32下要使用opengl的話,在建立視窗時,要增加此視窗對opengl的擴充套件的...

Win32程式設計 SetTimer的使用

settimer函式和wm timer訊息是win32 api中最基本的玩意兒了,任何初學win32 api程式設計的人都應該對此很熟悉吧。在這篇文章中,讓我們來深入了解一下和settimer相關的使用和應用。uint ptr settimer hwnd hwnd,uint ptr nidevent...