winapi簡單入門
2018-11-29
不要覺得奇怪,雖然我們擁有眾多「所見即所得」的程式設計方式來開發眾多介面精美的應
用程式,這些視覺化的程式設計環境提供了大量的類庫和控制項,但是在開發者享受方便的同時,
他們的手腳已經不知不覺的受到了限制,有很多深入到windows內部的操作它們無法完成,
為什麼?因為所用的類庫不支援。
programming inte***ce -- 應用程式設計介面 的縮寫,它不僅為應用程式所呼叫,同時也是
windows的一部分,windows自身的執行也呼叫這些api函式。要了解如何使用api就必須了
解一些windows的執行機制。
簡單地說,windows是由事件驅動的搶占式多工作業系統。事件驅動是相對於過程驅
動而言的,它改變了原來檔案的順序執行方式;windows既然是多工系統,就必須能同時
處理多個事件,系統為應用程式生成乙個訊息佇列,訊息在上面被張貼和傳送,應用程式只
要從其訊息佇列中取出訊息,然後一一執行就可以了。
現在,我將使用最最基本的範例程式 hellowin 來說明win32 api的執行機制
int apientry winmain(hinstance hinstance, hinstance hprevinstance,
lpstr lpcmdline,int ncmdshow)
hinstance是所謂的「例項控制代碼」,它是乙個數值,當程式在windows下執行的時候,它被用
來唯一的標示這個程式,雖然使用者可能同時執行多個同乙個程式,即執行多個「例項」,我
們可以看到,每乙個例項都有不同的hinstance值。
hprevinstance,簡單地說就是沒用…它是存在於16位windows程式中的,在編寫
windows 9x/nt/2000 程式的時候,總應該是null。
szcmdline是乙個指標,指向乙個以0為終結的字串,裡面包含傳給該程式的命令列引數,
如果想要讓程式處理命令列,那麼這個引數就有用了。
icmdshow引數是乙個數值,指示視窗將如何被顯示,這個數值由在windows下執行該程式的
程式所決定,通常是sw_shownormal。
接下來是註冊乙個視窗類,視窗總是從視窗類的基礎上建立的,視窗類用以標示處理視窗消
息的視窗過程,註冊視窗類時使用 registerclas***() 函式,它只需要乙個引數,乙個指向
型別為 wndclas*** 的結構指標。
具體註冊初始是這樣的:
wndclas*** wcex;
wcex.cbsize = sizeof(wndclas***); //結構的大小
wcex.style = cs_hredraw | cs_vredraw; //類風格
wcex.lpfnwndproc = (wndproc)wndproc; //視窗類的視窗過程
wcex.cbcl***tra = 0; //在類結構中預留的空間
wcex.cbwndextra = 0; //在windows內部儲存的視窗結構中預留的空間
wcex.hinstance = hinstance; //程式的例項控制代碼
wcex.hicon = loadicon(hinstance, (lpctstr)idi_example); //程式圖示
wcex.hcursor = loadcursor(null, idc_arrow); //結構的大小
wcex.hbrbackground = (hbrush)(color_window+1); //指定視窗的背景顏色
wcex.lpszmenuname = (lpcstr)idc_example; //選單
wcex.lpszclassname = szwindowclass; //類名,和程式名相同
wcex.hiconsm = loadicon(wcex.hinstance, (lpctstr)idi_small); //也是程式圖示
return registerclas***(&wcex);
接下來,定義乙個hwnd,然後使用 createwindow() 函式,原型如下:
hwnd createwindow(
lpctstr lpclassname, // 視窗類名
lpctstr lpwindowname, // 視窗標題
dword dwstyle, // 視窗風格
int x, // 初始x
int y, // 初始y
int nwidth, // 視窗寬
int nheight, // 視窗高
hwnd hwndparent, // 父視窗控制代碼
hmenu hmenu, // 選單控制代碼
hinstance hinstance, // 例項控制代碼
lpvoid lpparam // 建立引數
在 createwindow() 呼叫返回之後,windows內部已經建立了這視窗。但是視窗並為顯示,
還需要兩個呼叫,乙個是 showwindow(hwnd, icmdshow):第乙個引數是剛剛建立的視窗
控制代碼,第二個引數是傳遞給winmain的ncmdshow;另乙個是 updatewindow(hwnd) ,導致
客戶區域被繪製。
接下來,程式通過執行一塊被稱為「訊息迴圈」的**從訊息佇列中取出訊息
while (getmessage(&msg, null, 0, 0))
if (!translateaccelerator(msg.hwnd, hacceltable, &msg))
translatemessage(&msg);
dispatchmessage(&msg);
訊息迴圈以 getmessage 開始,它從訊息佇列中取出一條訊息,只要從訊息佇列中取出消
息的 message 域不為 wm_quit,getmessage 就返回乙個非零值,否則將導致程式退出
訊息迴圈,然後程式中止,返回 msg 結構的 wparam 引數。在迴圈中,translatemessage
將 msg 結構的內容進行修改,而 dispatchmessage 找出準備呼叫的視窗過程。
上面進行的僅僅是準備性工作:註冊視窗類、建立視窗、顯示視窗、進入訊息迴圈取出訊息
而實際的動作都發生在視窗過程中。
lresult callback wndproc(hwnd hwnd, //剛剛建立的視窗控制代碼
uint message, //得到的訊息
wparam wparam,
lparam lparam //訊息的進一步詳細的引數
在程式中視窗過程通常是命名為 wndproc 的函式,其實視窗過程可以任意的命名,乙個
windows程式可以包含多個視窗過程,乙個視窗過程總是與呼叫了 registerclas*** 註冊的
視窗類相關聯,createwindow 函式根據視窗類來建立視窗,但是乙個視窗類可以被用來創
建多個視窗。
訊息收到之後,接下來應該根據訊息的不同來進行處理
switch(message)
case …:
hellowin程式只需要處理兩條訊息,即 wm_paint 和 wm_destroy。
wm_paint 訊息在windows程式中的地位極其重要,當視窗客戶區的一部分或者全部變為
「無效」,必須進行重新整理的時候,將由這條訊息通知程式。
為什麼客戶區域會變得無效呢?在建立視窗的時候,整個客戶區都是無效的,因為還沒有畫
任何的東西。第一條 wm_paint 訊息指示視窗過程在視窗上面畫一些東西;還有在使用者改
變了視窗的大小之後,客戶區域重新變得無效,除此之外最小化視窗之後再還原、視窗的一
部分被覆蓋,都會引發這條訊息。
wm_destroy訊息則是當使用者按下「關閉」按鈕的時候被觸發,標準的處理方法是呼叫
postquitmessage 將一條 wm_quit 訊息插入訊息佇列,這將使得 getmessage 函式呼叫
返回0,從而退出訊息迴圈,結束整個程式。
其實,從上面可以看出,windows程式的這種執行機制並不是很難理解,真正困難的是不知
道呼叫什麼函式去完成想要的操作,以及怎樣呼叫那些函式,從而靈活的進行底層api程式
開發,這是乙個循序漸進的積累過程,沒有捷徑可走的。請各位一定要記住。
WinAPI 網路監聽程式的開發步驟(sniff)
老婆大人今天和他們同事們打羽毛球去了,閒著沒事把這兩天使用winapi做的乙個網路抓包監聽的程式步驟整理一下 我的程式參考了 visual c 網路通訊程式設計實用案例精選 這本書裡的乙個例子。方法 pragma comment lib,wsock32.lib pragma comment lib,...
開發屬於自己的AT指令(下)
本工程sdk基於esp8266 nonos sdk master版本為3.1。關於esp8266的at指令有以下基本形式。1 qurey形式,查詢某項資訊 格式 at test?2 setup形式,設定相關引數 格式 at test 1,abc 2 3 exec形式,執行某段程式 格式 at tes...
底層開發與並行程式設計
herb sutter 微軟c cli語言主設計師,預言 底層程式設計將再度流行 因為,晶元製造商發現他們無法保持現有的處理器效能增長速度.我想我們可能還剩5到10年時間 因為摩爾定律 他說,效能優化將再度變得非常,非常流行,那時人們將認識到抽象的代價 同時 sutter說,程式設計師將為並行的,多...