Windows內(nèi)部運行機制
Windos系統(tǒng)提供了各種各樣的函數(shù),這些函數(shù)是windows操作系統(tǒng)提供給應(yīng)用程序的接口 Application Progress Interface,所有主要的windows函數(shù)都在Windows.h頭文件中進行了聲明。
Win32 SDK(Soft Development Kit)是Windows 32平臺下的軟件開發(fā)包,包括API函數(shù),幫助文檔和一些輔助開發(fā)工具。
Windows是基于消息機制的,消息分標(biāo)準(zhǔn)消息,命令消息和通告消息。Windows程序中的消息又分進隊消息和不進隊消息,兩種消息都由消息響應(yīng)函數(shù)進行處理。
在VC中創(chuàng)建一個win32應(yīng)用程序的大概流程如下:
編寫WinMain函數(shù);
設(shè)計窗口類(WNDCLASS);
注冊窗口類(RegisterClass);
創(chuàng)建窗口(CreateWindow);
顯示并更新窗口(ShowWindow|UpdateWindow);
編寫消息循環(huán);
編寫窗口過程函數(shù)。
一個WinMain函數(shù)的原型如下:
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
);此處WINAPI是一個_stdcall宏定義,VC有很多宏定義,這個很讓人頭大,需要慢慢去習(xí)慣,從網(wǎng)絡(luò)上找了2中函數(shù)定義的說明與區(qū)別解釋。
__cdecl:這是編譯器默認(rèn)的函數(shù)調(diào)用轉(zhuǎn)換方式,它可以處理可變參數(shù)的函數(shù)調(diào)用。參數(shù)的入棧順序是從右向左。在函數(shù)運行結(jié)束后,由調(diào)用函數(shù)負責(zé)清理入棧的參數(shù)。在編譯時,在每個函數(shù)前面加上下劃線(_),沒有函數(shù)名大小寫的轉(zhuǎn)換。即_functionname.每一個調(diào)用它的函數(shù)都包含清空堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會比調(diào)用_stdcall函數(shù)的大。函數(shù)采用從右到左的壓棧方式。
__stdcall:函數(shù)參數(shù)從右向左入棧,被調(diào)用函數(shù)負責(zé)入棧參數(shù)的清理工作。函數(shù)名轉(zhuǎn)換格式如下:_functionname@number.函數(shù)參數(shù)個數(shù)固定。
WINDOWS 的函數(shù)調(diào)用時需要用到棧( STACK ,一種先入后出的存儲結(jié)構(gòu))。當(dāng)函數(shù)調(diào)用完成后,棧需要清除,這里就是問題的關(guān)鍵,如何清除?
如果函數(shù)使用 _cdecl ,那么棧的清除工作是由調(diào)用者,用 COM 的術(shù)語來講就是客戶來完成的。這樣帶來了一個棘手的問題,不同的編譯器產(chǎn)生棧的方式不盡相同,那么調(diào)用者能否正常的完成清除工作呢?答案是不能。
如果使用 __stdcall ,上面的問題就解決了,函數(shù)自己解決清除工作。所以,在跨(開發(fā))平臺的調(diào)用中,我們都使用 __stdcall (雖然有時是以 WINAPI 的樣子出現(xiàn))。
那么為什么還需要 _cdecl 呢?當(dāng)我們遇到這樣的函數(shù)如 fprintf() 它的參數(shù)是可變的,不定長的,被調(diào)用者事先無法知道參數(shù)的長度,事后的清除工作也無法正常的進行,因此,這種情況我們只能使用 _cdecl。
到這里有一個結(jié)論,如果你的程序中沒有涉及可變參數(shù),最好使用 __stdcall 關(guān)鍵字,我們創(chuàng)建一個Win32應(yīng)用程序都是用的系統(tǒng)API函數(shù),參數(shù)固定,所以都用__stdcall了。
設(shè)計窗口類、冊窗口類、創(chuàng)建窗口、顯示并更新窗口通常一起完成,MSDN中有詳細的說明,可以根據(jù)一些默認(rèn)參數(shù)修改窗口樣式。在完成窗口的設(shè)計,創(chuàng)建更新后,需要創(chuàng)建一個消息循環(huán)。
MSG msg;
while(GetMessage(&msg,NULL,0,0))//消息循環(huán)
{
TranslateMessage(&msg);//將虛擬鍵值消息轉(zhuǎn)化為字符消息,并將字符消息投遞到消息隊列中
DispatchMessage(&msg);//分派一個消息窗口,對消息進行處理
}
GetMessage函數(shù)接收到的消息除了WM_QUIT外都返回非零值。
消息響應(yīng)函數(shù)對消息隊列中的消息事件執(zhí)行處理,在窗口初始化的時候?qū)⒑瘮?shù)的指針提供給窗口,當(dāng)事件發(fā)生的時候調(diào)用函數(shù),消息響應(yīng)函數(shù)在定義前必須在窗口注冊,創(chuàng)建等過程前事先聲明。
DC:Device Contex,是一個包含設(shè)備信息的結(jié)構(gòu)體,這個地方的概念不大容易理解。
Windows創(chuàng)建了自己的命名約定,稱之為匈牙利命名法,通常在變量前面加上一些前綴字符。
最后,把原書的代碼抄一遍,雖然是照的書本寫,過程中還是出了一些錯誤,好不容易才調(diào)試完。VC開發(fā)環(huán)境的提示功能幾乎為零,god!
相關(guān)推薦:
北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |