1.2句柄及 WinMain函数
生活随笔
收集整理的這篇文章主要介紹了
1.2句柄及 WinMain函数
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
***********************************************
* ? 本文由小鳥飛飛整理發(fā)表 <samboy@sohu.com> ? *
* ? 首發(fā)網(wǎng)站:藍麗網(wǎng) ? ?? ?? ?? ?? ?? ?? *
* ? 其他網(wǎng)站轉(zhuǎn)載請保留以上信息,謝謝! ? ?? ?*
************************************************
關(guān) 于句柄
在Windows編程中我們時刻接觸到一個稱為句柄(HANDLE)的東西。可以這樣去理解句柄,Windows程序中產(chǎn)生的任何資源 (要占用某一塊或大或小的內(nèi)存),如圖標(biāo),光標(biāo),窗口,應(yīng)用程序的實例(已加載到內(nèi)存運行中的程序)。操作系統(tǒng)每產(chǎn)生一個這樣的資源時,都要將它們放入相 應(yīng)的內(nèi)存,并為這些內(nèi)存指定一個唯一的標(biāo)識號,這個標(biāo)識號即該資源的句柄。
操作系統(tǒng)要管理和操作這些資源,都是通過句柄來找到對應(yīng)的 資源的。按資源的類型,又可將句柄細分成圖標(biāo)句柄(HICON),光標(biāo)句柄(HCURSOR),窗口句柄(HWND),應(yīng)用程序?qū)嵗浔?(HINSTANCE),等等各種類型的句柄。操作系統(tǒng)給每一個窗口指定的一個唯一的標(biāo)識號即窗口句柄。
WinMain函數(shù)
WinMain是Windows程序的入口點函數(shù),同dos程序的入口點函數(shù)main的作用相同,當(dāng)WinMain函數(shù)結(jié)束或返回時,Windows應(yīng)用 程序結(jié)束。WinMain函數(shù)的原型如下:
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, ? ?// pointer to command line
int nCmdShow ? ?? ?// show state of window
);
該函數(shù)接受四個參數(shù),這些參數(shù)都 是系統(tǒng)調(diào)用WinMain函數(shù)時,傳遞給應(yīng)用程序的。
第一個參數(shù)hInstance表示該程序的當(dāng)前運行的實例句柄。同一應(yīng)用程序在 同一計算機上可運行多份實例,每啟動一個這樣的實例,操作系統(tǒng)都要給該實例分配一個標(biāo)識號,即實例句柄,隨后系統(tǒng)調(diào)用程序中的WinMain函數(shù),并將該 實例句柄傳遞給參數(shù)hInstance。
第二個參數(shù)hPrevInstance表示當(dāng)前實例的上一個正在運行的,由同一個應(yīng)用程序所 產(chǎn)生的實例的句柄,即當(dāng)前實例的"哥哥"的句柄。如果該值為NULL,則表示當(dāng)前實例是該程序正在運行的第一份實例,是“長子”,是“老大”。如果該值不 為NULL,只能表示當(dāng)前實例不是該程序正在運行的第一份實例,不是“長子”,不是“老大”,但到底是“老幾”,就無從得知了。這個參數(shù)到底有什么作用 呢?如果想讓我們的程序只能有一份實例運行,不能同時有多份實例運行,我們可以在WinMain函數(shù)的開始部分加上如下代碼實現(xiàn)。
if(hPrevInstance) return 0;
我們再來看看if(hPrevInstance) return 0;的作用,如果hPrevInstance為NULL(即0),說明當(dāng)前運行的實例是程序的第一個實例,WinMain函數(shù)將不返回,程序正常向下運 行。只要hPrevInstance不為NULL,說明已經(jīng)有同樣程序的實例在運行,WinMain函數(shù)將返回,當(dāng)前實例啟動后立馬結(jié)束,這樣就保證了只 有程序的一個實例可以運行。
第三個參數(shù)lpCmdLine是一個字符串,里面包含有傳遞給應(yīng)用程序的參數(shù)串,如:雙擊C盤下的 1.txt文件方式啟動notepad.exe程序,傳遞給notepad.exe程序的參數(shù)串即"c:\1.txt",不包含應(yīng)用程序名本身。要在VC 開發(fā)環(huán)境中給應(yīng)用程序傳遞參數(shù),請選擇菜單Project->Settings...,在彈出的Project Settings對話框中選擇Debug標(biāo)簽,在該標(biāo)簽頁的Program arguments編輯框中輸入你想傳遞給應(yīng)用程序的參數(shù)。我們在WinMain函數(shù)的入口點設(shè)置一運行斷點,以調(diào)試方式啟動程序運行至該斷點處,將鼠標(biāo) 移動到參數(shù)lpCmdLine上,在彈出的黃色小浮框中便能觀察到該變量的值。在我們的程序調(diào)試中,經(jīng)常要用到這種方法查看變量的值和狀態(tài)。
第四個參數(shù)nCmdShow指定的程序的窗口應(yīng)該如何顯示,如最大化,最小化,隱藏等。
WinMain函數(shù)前的修飾符WINAPI 的解釋,我們使用goto definition功能,發(fā)現(xiàn)WINAPI其實就是__stdcall。
__stdcall與 __cdecl是兩種不同的函數(shù)調(diào)用習(xí)慣,定義了參數(shù)的傳遞順序、堆棧清除等。關(guān)于它們的詳細信息請參看msdn。由于除了那些可變參數(shù)的API函數(shù)外, 其余的API函數(shù)都是__stdcall習(xí)慣。由于VC++程序默認的編譯選項是__cdecl,所以在VC++中調(diào)用這些__stdcall習(xí)慣的 API函數(shù),必須在聲明這些函數(shù)的原型時加上__stdcall修飾符,以便對該函數(shù)的調(diào)用使用__stdcall習(xí)慣。我們曾有這樣的經(jīng)驗,在 Delphi(默認的編譯選項是__stdcall)中編寫的dll中的函數(shù),在VC++中被調(diào)用時,總是造成程序崩潰,在函數(shù)的原型聲明中加上 __stdcall修飾符,便解決了這個問題。回調(diào)函數(shù)也必須是__stdcall調(diào)用習(xí)慣,在這里是用CALLBACK來標(biāo)識的,否則,在NT4.0環(huán) 境,程序?qū)⒈罎?#xff0c;但win98和win2000卻沒有這種現(xiàn)象。
Winmain函數(shù)的程序代碼按功能劃分主要有兩部分:1.產(chǎn)生并顯 示程序的主窗口。窗口創(chuàng)建并顯示后,用戶便可以在窗口上進行各種操作了,用戶的操作及程序狀態(tài)的變化都以消息的形式放到了應(yīng)用程序的消息隊列中。2.從消 息隊列循環(huán)取走消息,并將消息派發(fā)到窗口過程函數(shù)中去處理。當(dāng)消息循環(huán)取到一條WM_QUIT消息時,將結(jié)束循環(huán),WinMain函數(shù)返回,結(jié)束整個程序 的運行。
如果WinMain在消息循環(huán)之前返回,程序沒有正常運行,返回值為0。如果在消息循環(huán)之后返回,返回值為WM_QIUT消息的 wParam參數(shù)。
* ? 本文由小鳥飛飛整理發(fā)表 <samboy@sohu.com> ? *
* ? 首發(fā)網(wǎng)站:藍麗網(wǎng) ? ?? ?? ?? ?? ?? ?? *
* ? 其他網(wǎng)站轉(zhuǎn)載請保留以上信息,謝謝! ? ?? ?*
************************************************
關(guān) 于句柄
在Windows編程中我們時刻接觸到一個稱為句柄(HANDLE)的東西。可以這樣去理解句柄,Windows程序中產(chǎn)生的任何資源 (要占用某一塊或大或小的內(nèi)存),如圖標(biāo),光標(biāo),窗口,應(yīng)用程序的實例(已加載到內(nèi)存運行中的程序)。操作系統(tǒng)每產(chǎn)生一個這樣的資源時,都要將它們放入相 應(yīng)的內(nèi)存,并為這些內(nèi)存指定一個唯一的標(biāo)識號,這個標(biāo)識號即該資源的句柄。
操作系統(tǒng)要管理和操作這些資源,都是通過句柄來找到對應(yīng)的 資源的。按資源的類型,又可將句柄細分成圖標(biāo)句柄(HICON),光標(biāo)句柄(HCURSOR),窗口句柄(HWND),應(yīng)用程序?qū)嵗浔?(HINSTANCE),等等各種類型的句柄。操作系統(tǒng)給每一個窗口指定的一個唯一的標(biāo)識號即窗口句柄。
WinMain函數(shù)
WinMain是Windows程序的入口點函數(shù),同dos程序的入口點函數(shù)main的作用相同,當(dāng)WinMain函數(shù)結(jié)束或返回時,Windows應(yīng)用 程序結(jié)束。WinMain函數(shù)的原型如下:
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, ? ?// pointer to command line
int nCmdShow ? ?? ?// show state of window
);
該函數(shù)接受四個參數(shù),這些參數(shù)都 是系統(tǒng)調(diào)用WinMain函數(shù)時,傳遞給應(yīng)用程序的。
第一個參數(shù)hInstance表示該程序的當(dāng)前運行的實例句柄。同一應(yīng)用程序在 同一計算機上可運行多份實例,每啟動一個這樣的實例,操作系統(tǒng)都要給該實例分配一個標(biāo)識號,即實例句柄,隨后系統(tǒng)調(diào)用程序中的WinMain函數(shù),并將該 實例句柄傳遞給參數(shù)hInstance。
第二個參數(shù)hPrevInstance表示當(dāng)前實例的上一個正在運行的,由同一個應(yīng)用程序所 產(chǎn)生的實例的句柄,即當(dāng)前實例的"哥哥"的句柄。如果該值為NULL,則表示當(dāng)前實例是該程序正在運行的第一份實例,是“長子”,是“老大”。如果該值不 為NULL,只能表示當(dāng)前實例不是該程序正在運行的第一份實例,不是“長子”,不是“老大”,但到底是“老幾”,就無從得知了。這個參數(shù)到底有什么作用 呢?如果想讓我們的程序只能有一份實例運行,不能同時有多份實例運行,我們可以在WinMain函數(shù)的開始部分加上如下代碼實現(xiàn)。
if(hPrevInstance) return 0;
我們再來看看if(hPrevInstance) return 0;的作用,如果hPrevInstance為NULL(即0),說明當(dāng)前運行的實例是程序的第一個實例,WinMain函數(shù)將不返回,程序正常向下運 行。只要hPrevInstance不為NULL,說明已經(jīng)有同樣程序的實例在運行,WinMain函數(shù)將返回,當(dāng)前實例啟動后立馬結(jié)束,這樣就保證了只 有程序的一個實例可以運行。
第三個參數(shù)lpCmdLine是一個字符串,里面包含有傳遞給應(yīng)用程序的參數(shù)串,如:雙擊C盤下的 1.txt文件方式啟動notepad.exe程序,傳遞給notepad.exe程序的參數(shù)串即"c:\1.txt",不包含應(yīng)用程序名本身。要在VC 開發(fā)環(huán)境中給應(yīng)用程序傳遞參數(shù),請選擇菜單Project->Settings...,在彈出的Project Settings對話框中選擇Debug標(biāo)簽,在該標(biāo)簽頁的Program arguments編輯框中輸入你想傳遞給應(yīng)用程序的參數(shù)。我們在WinMain函數(shù)的入口點設(shè)置一運行斷點,以調(diào)試方式啟動程序運行至該斷點處,將鼠標(biāo) 移動到參數(shù)lpCmdLine上,在彈出的黃色小浮框中便能觀察到該變量的值。在我們的程序調(diào)試中,經(jīng)常要用到這種方法查看變量的值和狀態(tài)。
第四個參數(shù)nCmdShow指定的程序的窗口應(yīng)該如何顯示,如最大化,最小化,隱藏等。
WinMain函數(shù)前的修飾符WINAPI 的解釋,我們使用goto definition功能,發(fā)現(xiàn)WINAPI其實就是__stdcall。
__stdcall與 __cdecl是兩種不同的函數(shù)調(diào)用習(xí)慣,定義了參數(shù)的傳遞順序、堆棧清除等。關(guān)于它們的詳細信息請參看msdn。由于除了那些可變參數(shù)的API函數(shù)外, 其余的API函數(shù)都是__stdcall習(xí)慣。由于VC++程序默認的編譯選項是__cdecl,所以在VC++中調(diào)用這些__stdcall習(xí)慣的 API函數(shù),必須在聲明這些函數(shù)的原型時加上__stdcall修飾符,以便對該函數(shù)的調(diào)用使用__stdcall習(xí)慣。我們曾有這樣的經(jīng)驗,在 Delphi(默認的編譯選項是__stdcall)中編寫的dll中的函數(shù),在VC++中被調(diào)用時,總是造成程序崩潰,在函數(shù)的原型聲明中加上 __stdcall修飾符,便解決了這個問題。回調(diào)函數(shù)也必須是__stdcall調(diào)用習(xí)慣,在這里是用CALLBACK來標(biāo)識的,否則,在NT4.0環(huán) 境,程序?qū)⒈罎?#xff0c;但win98和win2000卻沒有這種現(xiàn)象。
Winmain函數(shù)的程序代碼按功能劃分主要有兩部分:1.產(chǎn)生并顯 示程序的主窗口。窗口創(chuàng)建并顯示后,用戶便可以在窗口上進行各種操作了,用戶的操作及程序狀態(tài)的變化都以消息的形式放到了應(yīng)用程序的消息隊列中。2.從消 息隊列循環(huán)取走消息,并將消息派發(fā)到窗口過程函數(shù)中去處理。當(dāng)消息循環(huán)取到一條WM_QUIT消息時,將結(jié)束循環(huán),WinMain函數(shù)返回,結(jié)束整個程序 的運行。
如果WinMain在消息循環(huán)之前返回,程序沒有正常運行,返回值為0。如果在消息循環(huán)之后返回,返回值為WM_QIUT消息的 wParam參數(shù)。
總結(jié)
以上是生活随笔為你收集整理的1.2句柄及 WinMain函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1.1 Windows 程序运行原理(消
- 下一篇: 1.4 消息循环和回调函数