上一篇,講了一個(gè)簡(jiǎn)單的SDK程序的多種版本的編寫,彈出了一個(gè)窗口,顯示了我們計(jì)算1到10的結(jié)果,計(jì)算的程序不是重點(diǎn),重點(diǎn)在于,一:讓大家認(rèn)識(shí)到Unicode版本的程序和ASCII版本的程序在編程方面的區(qū)別,以及怎么樣編寫出通用代碼的程序。二:怎么樣運(yùn)用API或者c++庫(kù)函數(shù)格式化非字符數(shù)據(jù)到一個(gè)字符串中顯示出來。
不過,那個(gè)相當(dāng)簡(jiǎn)單的程序,還算不上是一個(gè)正兒八經(jīng)的SDK程序,也就是說還不是一個(gè)純爺們兒,因?yàn)槲覀儾⒂H自完成一個(gè)SDK程序的經(jīng)典步驟。而是調(diào)用了一個(gè)MessageBox API函數(shù),這個(gè)函數(shù)雖然使用簡(jiǎn)單,但是在它的內(nèi)部,那可是相當(dāng)復(fù)雜啊~~~。怎么個(gè)復(fù)雜法,具體的我不知道,但是我知道的是一個(gè)SDK程序的經(jīng)典步驟它是都用到了的,什么是編寫SDK程序的經(jīng)典步驟呢?新手朋友們聽好了哦,現(xiàn)在我就告訴你。
第一步:注冊(cè)窗口類
第二步:創(chuàng)建窗口
第三步:消息循環(huán)
第四步:編寫窗口消息處理函數(shù)
上面我所說的,聽起來都比較專業(yè),下面我就解釋一下,什么是注冊(cè)窗口類呢?注冊(cè)窗口類就是使用一個(gè) 窗口類結(jié)構(gòu)體(WNDCLASSEX) 來描述一類窗口,這類窗口具有相同的屬性,也就是你在結(jié)構(gòu)體WNDCLASSEX中指定的那些值。只要是用這個(gè)窗口類創(chuàng)建的窗口都具有這些特性。至于WNDCLASS能描述哪些特性,下面會(huì)具體講,這里你只要了解是用一個(gè)名叫WNDCLASSEX的結(jié)構(gòu)體來描述一個(gè)窗口的類別。
創(chuàng)建窗口應(yīng)該比較好理解吧,就是創(chuàng)建一個(gè)具體的窗口,好像是一句廢話嘛。也就是說這個(gè)窗口是根據(jù)一個(gè)窗口類而創(chuàng)建的,不是憑空而造的。意思是你要?jiǎng)?chuàng)建一個(gè)窗口,那么必須要有一個(gè)已經(jīng)注冊(cè)的窗口類。
對(duì)于前兩步,我打一個(gè)比方,就好比你要造一輛車,那們第一步首先是干什么? 當(dāng)然是設(shè)計(jì)圖紙啦,圖紙上就有說明這種車有哪些特性。然后第二步才是根據(jù)這個(gè)圖紙來創(chuàng)建一個(gè)具體的看得見的車。所以我上面說的注冊(cè)窗口類就好比設(shè)計(jì)窗口的圖紙,然后就是根據(jù)這個(gè)窗口的圖紙來創(chuàng)建一個(gè)具體的窗口。都說成這樣了,應(yīng)該明了了吧~~
至于消息循環(huán),就是創(chuàng)建的窗口隨時(shí)都有可能發(fā)生很多事情,那么發(fā)生的這些事情怎么通知你呢?比如窗口最小化了,窗口大小改變了,怎么通知你呢? 其實(shí)就就是通過消息循環(huán)不斷的取得窗口所發(fā)生的事情,然后以消息的形式發(fā)送給我們后面要介紹的窗口消息處理函數(shù)。
消息處理函數(shù)呢就是我們程序員負(fù)責(zé)編寫代碼對(duì)具體的消息進(jìn)行具體的處理,當(dāng)然你也可以不處理,交給系統(tǒng)的默認(rèn)處理函數(shù)來處理。
對(duì)于這兩步,我也打一個(gè)比方。消息循環(huán)就好比汽車的一個(gè)總傳感器,它源源不斷的將汽車內(nèi)部所發(fā)生的事情以消息的形式通過儀表板傳達(dá)給開車的人,開車的人根據(jù)具體的事情而采取具體的操作,當(dāng)然你也可以不操作,無動(dòng)于衷,對(duì)于windows消息來說,不操作倒沒有什么,而對(duì)于開車的人來說,不操作的后果就不好說了。 在這里,這個(gè)總傳感器就相當(dāng)于SDK程序的消息循環(huán),不斷的發(fā)送消息,而開車的人就相當(dāng)于窗口消息處理函數(shù),負(fù)責(zé)處理各種消息。明白了吧,還不明白的話就看看下面的具體的程序吧,也需還有最后一絲希望可以讓你恍然大悟。
講了正兒八經(jīng)的SDK程序的經(jīng)典步驟后,我們進(jìn)入正式的代碼階段,通過代碼結(jié)合上面所講理論進(jìn)一步鞏固知識(shí)。我講逐步講解并逐步編寫一個(gè)自己注冊(cè)窗口類,創(chuàng)建窗口,帶消息循環(huán),并自己編寫消息處理過程的程序。
首先給出程序框架
/* BY beyondcode */
#include
#include
LRESULT CALLBACK WinMessageProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd )
{
return 0;
}
第一個(gè)函數(shù)聲明,返回類型為L(zhǎng)RESULT,本質(zhì)經(jīng)查看是long,然后函數(shù)調(diào)用約定CALLBACK和WINAPI是一樣的,都是__stdcall,說明函數(shù)調(diào)用相關(guān)的約定,不必深究。你只負(fù)責(zé)編寫它的代碼,至于調(diào)用,系統(tǒng)會(huì)在有消息的時(shí)候自動(dòng)調(diào)用它。WinMessageProc的參數(shù)類型和個(gè)數(shù)是規(guī)定好了的,不然系統(tǒng)怎么知道怎么掉用,所以不能更改。
再解釋一下這四個(gè)參數(shù)吧,第一個(gè)參數(shù)是一個(gè)窗口的句柄,也就是告訴你,是哪個(gè)窗口的消息,第二個(gè)參數(shù)是消息的類型,告訴你是什么消息,第三個(gè)和第四個(gè)參數(shù)是這個(gè)消息所帶的一些額外的但是必須的數(shù)據(jù)。你在窗口消息處理函數(shù)中只使用他們就可以了,他們的值都是系統(tǒng)傳遞進(jìn)來的。你只是根據(jù)他們來判斷是哪個(gè)窗口的什么消息,并且獲取該消息的額外參數(shù)信息。
有了程序框架,我們來第一步,注冊(cè)一個(gè)窗口類
//注冊(cè)一個(gè)名叫MyWindowClass的窗口類
WNDCLASSEX wc;
wc.cbSize = sizeof( wc );
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
wc.hInstance = hInstance;
wc.lpfnWndProc = WinMessageProc;
wc.lpszMenuName = NULL;
wc.lpszClassName = _T("MyWindowClass");
if( !RegisterClassEx( &wc ) )
{
MessageBox( NULL, _T("注冊(cè)窗口類出錯(cuò)"), _T("出錯(cuò)"), MB_OK );
return 0;
} 上面的WNDCLASS的各個(gè)成員值我就不一一介紹是什么含義,MSDN上面講的非常清楚,我只講一兩個(gè)比較重點(diǎn)的,第一個(gè)lpszClassName這個(gè)成員,我們給它指定的是_T("MyWindowClass")這個(gè)擔(dān)饈侵付ㄕ飧齟翱誒嗟拿質(zhì)鞘裁?,因为下脣鼓创建窗空熱用到这个名讕?/p>
lpfnWndProc這個(gè)成員是WinMessageProc這個(gè)函數(shù),這是指定這個(gè)窗口類所創(chuàng)建的窗口的消息處理函數(shù)是哪一個(gè),我們這里指定的是WinMessageProc。其他的參數(shù)我就不啰嗦了,各位不懂的MSDN一下或者在群里來交流一下。
指定了這個(gè)窗口類有哪些特性后就完了?當(dāng)然沒有,沒有注冊(cè)怎么使用啊,所以還需要注冊(cè),注冊(cè)調(diào)用RegisterClassEx這個(gè)API函數(shù),將剛才的WNDCLASS變量的地址傳給它就可以進(jìn)行注冊(cè)了,如果注冊(cè)失敗,返回值為零,成功的話返回值為非零。
注冊(cè)了窗口類,我們來第二步,創(chuàng)建一個(gè)窗口。代碼如下:
// 根據(jù)上面注冊(cè)的一個(gè)名叫MyWindowClass 的窗口類創(chuàng)建窗口
HWND newWind = CreateWindowEx( 0L, _T("MyWindowClass"), _T("beyondcode"), WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, NULL, NULL, hInstance, NULL );
if( NULL==newWind )
{
MessageBox( NULL, _T("創(chuàng)建窗口出錯(cuò)"), _T("出錯(cuò)"), MB_OK );
return 0;
}
ShowWindow( newWind, nShowCmd );
UpdateWindow( newWind );
可見,創(chuàng)建窗口用CreateWindowEx這個(gè)API函數(shù),它的第一個(gè)參數(shù)是擴(kuò)展樣式,我們這里不設(shè)置擴(kuò)展樣式,所以傳遞0L,第二個(gè)參數(shù)就是窗口類的名字,我們這里指定我們上面已經(jīng)注冊(cè)了的那個(gè)名叫MyWindowClass的窗口類,第三個(gè)參數(shù)是窗口的標(biāo)題,隨便設(shè)置,第四個(gè)參數(shù)是窗口的樣式,我們這里設(shè)置的是WS_OVERLAPPEDWINDOW,一般主窗口都用這個(gè)樣式,就是有化,最小化框,有標(biāo)題欄,有系統(tǒng)菜單。。具體的可以參見MSDN,第五個(gè),六個(gè),七個(gè),八個(gè)參數(shù)分別指定窗口的初始坐標(biāo)和長(zhǎng)寬,第九個(gè)參數(shù)指定父窗口是哪個(gè),這里沒有父窗口,所以傳遞NULL,第十個(gè)參數(shù)指定菜單的句柄,我們這里不設(shè)置菜單,所以傳遞NULL,第十一個(gè)是應(yīng)用程序句柄,用WinMain傳遞進(jìn)來的那個(gè)hInstance參數(shù),第十二個(gè)參數(shù)表示額外數(shù)據(jù),不設(shè)置,所以為NULL。
這個(gè)API函數(shù)有點(diǎn)復(fù)雜,不過用熟悉了也就不覺得了。這樣我們就創(chuàng)建了一個(gè)窗口,返回值是一個(gè)窗口的句柄,如果是NULL的話,說明創(chuàng)建窗口失敗了,如果不是NULL的話,說明成功了。
ShowWindow和UpdateWindow,參數(shù)就是剛才創(chuàng)建成功的那個(gè)窗口的句柄,至于ShowWindow的第二個(gè)參數(shù)是指顯示的類型,是化顯示呢還是最小化顯示呢,不過在程序中第一次調(diào)用ShowWindow必須使用WinMain所傳遞進(jìn)來的參數(shù)的第四個(gè)參數(shù)的值。這是MSDN上說的~
窗口創(chuàng)建成功了,下面一步是消息循環(huán)了,消息循環(huán)說起來復(fù)雜,其實(shí)代碼挺簡(jiǎn)單的,而且基本格式固定,如下:
//消息循環(huán)
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
看到了嗎? 一直在一個(gè)循環(huán)里面,一直調(diào)用GetMessage,只要GetMessage所取得的消息不是WM_QUIT的話,那么GetMessage的返回值就不是0,那么循環(huán)就一直進(jìn)行。在循環(huán)內(nèi)部,將GetMessage取得的消息傳遞給TranslateMessage和DispatchMessage兩個(gè)API函數(shù)進(jìn)行處理.其中DispatchMessage就是將消息發(fā)送給了對(duì)應(yīng)的窗口的窗口消息處理函數(shù)進(jìn)行處理。至于TranslateMessage呢,則進(jìn)行一些消息的轉(zhuǎn)換,可以先不深究。
最后就是編寫窗口消息處理函數(shù)的代碼了,你需要處理那些消息,那么你就編寫處理那些消息的代碼,對(duì)于你不處理的消息,則統(tǒng)統(tǒng)交給一個(gè)叫DefWindowProc的API函數(shù)進(jìn)行默認(rèn)的處理。
LRESULT CALLBACK WinMessageProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch ( msg )
{
case WM_DESTROY:
{
PostQuitMessage( 0 );
break;
}
default:
return DefWindowProc( hwnd, msg, wParam, lParam );
}
return 0;
}
這里我們只處理了WM_DESTROY這個(gè)消息,這個(gè)消息是在窗口被銷毀的時(shí)候發(fā)送給窗口消息處理函數(shù)的,在窗口處理函數(shù)中,我們判斷這個(gè)消息是不是WM_DESTROY,如果是,就調(diào)用PostQuitMessage這個(gè)API函數(shù),如果是其他消息,我們就不管,將參數(shù)全部傳遞給DefWindowProc這個(gè)函數(shù)進(jìn)行處理。
而PostQuitMessage這個(gè)API函數(shù)的功能就是發(fā)送一個(gè)WM_QUIT的消息。而我們前面說到過, 在消息循環(huán)中GetMessage一旦取得WM_QUIT這個(gè)消息,就返回值為0,那么消息循環(huán)也就結(jié)束了,進(jìn)而整個(gè)程序也就結(jié)束了,如果在這里我們處理WM_DESTORY函數(shù),但是不調(diào)用PostQuitMessage,那么結(jié)果會(huì)怎樣呢,讀者朋友們思考一下~~
好了,到這里,這個(gè)什么功能也沒有的SDK程序也就完了,它只顯示一個(gè)帶有標(biāo)題欄的可化,最小化的窗口,除了能夠關(guān)閉它,你幾乎不能進(jìn)行其他任何操作,因?yàn)槲覀兂颂幚泶翱阡N毀這個(gè)消息,其他任何消息我們都沒處理。
不過,那個(gè)相當(dāng)簡(jiǎn)單的程序,還算不上是一個(gè)正兒八經(jīng)的SDK程序,也就是說還不是一個(gè)純爺們兒,因?yàn)槲覀儾⒂H自完成一個(gè)SDK程序的經(jīng)典步驟。而是調(diào)用了一個(gè)MessageBox API函數(shù),這個(gè)函數(shù)雖然使用簡(jiǎn)單,但是在它的內(nèi)部,那可是相當(dāng)復(fù)雜啊~~~。怎么個(gè)復(fù)雜法,具體的我不知道,但是我知道的是一個(gè)SDK程序的經(jīng)典步驟它是都用到了的,什么是編寫SDK程序的經(jīng)典步驟呢?新手朋友們聽好了哦,現(xiàn)在我就告訴你。
第一步:注冊(cè)窗口類
第二步:創(chuàng)建窗口
第三步:消息循環(huán)
第四步:編寫窗口消息處理函數(shù)
上面我所說的,聽起來都比較專業(yè),下面我就解釋一下,什么是注冊(cè)窗口類呢?注冊(cè)窗口類就是使用一個(gè) 窗口類結(jié)構(gòu)體(WNDCLASSEX) 來描述一類窗口,這類窗口具有相同的屬性,也就是你在結(jié)構(gòu)體WNDCLASSEX中指定的那些值。只要是用這個(gè)窗口類創(chuàng)建的窗口都具有這些特性。至于WNDCLASS能描述哪些特性,下面會(huì)具體講,這里你只要了解是用一個(gè)名叫WNDCLASSEX的結(jié)構(gòu)體來描述一個(gè)窗口的類別。
創(chuàng)建窗口應(yīng)該比較好理解吧,就是創(chuàng)建一個(gè)具體的窗口,好像是一句廢話嘛。也就是說這個(gè)窗口是根據(jù)一個(gè)窗口類而創(chuàng)建的,不是憑空而造的。意思是你要?jiǎng)?chuàng)建一個(gè)窗口,那么必須要有一個(gè)已經(jīng)注冊(cè)的窗口類。
對(duì)于前兩步,我打一個(gè)比方,就好比你要造一輛車,那們第一步首先是干什么? 當(dāng)然是設(shè)計(jì)圖紙啦,圖紙上就有說明這種車有哪些特性。然后第二步才是根據(jù)這個(gè)圖紙來創(chuàng)建一個(gè)具體的看得見的車。所以我上面說的注冊(cè)窗口類就好比設(shè)計(jì)窗口的圖紙,然后就是根據(jù)這個(gè)窗口的圖紙來創(chuàng)建一個(gè)具體的窗口。都說成這樣了,應(yīng)該明了了吧~~
至于消息循環(huán),就是創(chuàng)建的窗口隨時(shí)都有可能發(fā)生很多事情,那么發(fā)生的這些事情怎么通知你呢?比如窗口最小化了,窗口大小改變了,怎么通知你呢? 其實(shí)就就是通過消息循環(huán)不斷的取得窗口所發(fā)生的事情,然后以消息的形式發(fā)送給我們后面要介紹的窗口消息處理函數(shù)。
消息處理函數(shù)呢就是我們程序員負(fù)責(zé)編寫代碼對(duì)具體的消息進(jìn)行具體的處理,當(dāng)然你也可以不處理,交給系統(tǒng)的默認(rèn)處理函數(shù)來處理。
對(duì)于這兩步,我也打一個(gè)比方。消息循環(huán)就好比汽車的一個(gè)總傳感器,它源源不斷的將汽車內(nèi)部所發(fā)生的事情以消息的形式通過儀表板傳達(dá)給開車的人,開車的人根據(jù)具體的事情而采取具體的操作,當(dāng)然你也可以不操作,無動(dòng)于衷,對(duì)于windows消息來說,不操作倒沒有什么,而對(duì)于開車的人來說,不操作的后果就不好說了。 在這里,這個(gè)總傳感器就相當(dāng)于SDK程序的消息循環(huán),不斷的發(fā)送消息,而開車的人就相當(dāng)于窗口消息處理函數(shù),負(fù)責(zé)處理各種消息。明白了吧,還不明白的話就看看下面的具體的程序吧,也需還有最后一絲希望可以讓你恍然大悟。
講了正兒八經(jīng)的SDK程序的經(jīng)典步驟后,我們進(jìn)入正式的代碼階段,通過代碼結(jié)合上面所講理論進(jìn)一步鞏固知識(shí)。我講逐步講解并逐步編寫一個(gè)自己注冊(cè)窗口類,創(chuàng)建窗口,帶消息循環(huán),并自己編寫消息處理過程的程序。
首先給出程序框架
/* BY beyondcode */
#include
#include
LRESULT CALLBACK WinMessageProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd )
{
return 0;
}
第一個(gè)函數(shù)聲明,返回類型為L(zhǎng)RESULT,本質(zhì)經(jīng)查看是long,然后函數(shù)調(diào)用約定CALLBACK和WINAPI是一樣的,都是__stdcall,說明函數(shù)調(diào)用相關(guān)的約定,不必深究。你只負(fù)責(zé)編寫它的代碼,至于調(diào)用,系統(tǒng)會(huì)在有消息的時(shí)候自動(dòng)調(diào)用它。WinMessageProc的參數(shù)類型和個(gè)數(shù)是規(guī)定好了的,不然系統(tǒng)怎么知道怎么掉用,所以不能更改。
再解釋一下這四個(gè)參數(shù)吧,第一個(gè)參數(shù)是一個(gè)窗口的句柄,也就是告訴你,是哪個(gè)窗口的消息,第二個(gè)參數(shù)是消息的類型,告訴你是什么消息,第三個(gè)和第四個(gè)參數(shù)是這個(gè)消息所帶的一些額外的但是必須的數(shù)據(jù)。你在窗口消息處理函數(shù)中只使用他們就可以了,他們的值都是系統(tǒng)傳遞進(jìn)來的。你只是根據(jù)他們來判斷是哪個(gè)窗口的什么消息,并且獲取該消息的額外參數(shù)信息。
有了程序框架,我們來第一步,注冊(cè)一個(gè)窗口類
//注冊(cè)一個(gè)名叫MyWindowClass的窗口類
WNDCLASSEX wc;
wc.cbSize = sizeof( wc );
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
wc.hInstance = hInstance;
wc.lpfnWndProc = WinMessageProc;
wc.lpszMenuName = NULL;
wc.lpszClassName = _T("MyWindowClass");
if( !RegisterClassEx( &wc ) )
{
MessageBox( NULL, _T("注冊(cè)窗口類出錯(cuò)"), _T("出錯(cuò)"), MB_OK );
return 0;
} 上面的WNDCLASS的各個(gè)成員值我就不一一介紹是什么含義,MSDN上面講的非常清楚,我只講一兩個(gè)比較重點(diǎn)的,第一個(gè)lpszClassName這個(gè)成員,我們給它指定的是_T("MyWindowClass")這個(gè)擔(dān)饈侵付ㄕ飧齟翱誒嗟拿質(zhì)鞘裁?,因为下脣鼓创建窗空熱用到这个名讕?/p>
lpfnWndProc這個(gè)成員是WinMessageProc這個(gè)函數(shù),這是指定這個(gè)窗口類所創(chuàng)建的窗口的消息處理函數(shù)是哪一個(gè),我們這里指定的是WinMessageProc。其他的參數(shù)我就不啰嗦了,各位不懂的MSDN一下或者在群里來交流一下。
指定了這個(gè)窗口類有哪些特性后就完了?當(dāng)然沒有,沒有注冊(cè)怎么使用啊,所以還需要注冊(cè),注冊(cè)調(diào)用RegisterClassEx這個(gè)API函數(shù),將剛才的WNDCLASS變量的地址傳給它就可以進(jìn)行注冊(cè)了,如果注冊(cè)失敗,返回值為零,成功的話返回值為非零。
注冊(cè)了窗口類,我們來第二步,創(chuàng)建一個(gè)窗口。代碼如下:
// 根據(jù)上面注冊(cè)的一個(gè)名叫MyWindowClass 的窗口類創(chuàng)建窗口
HWND newWind = CreateWindowEx( 0L, _T("MyWindowClass"), _T("beyondcode"), WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, NULL, NULL, hInstance, NULL );
if( NULL==newWind )
{
MessageBox( NULL, _T("創(chuàng)建窗口出錯(cuò)"), _T("出錯(cuò)"), MB_OK );
return 0;
}
ShowWindow( newWind, nShowCmd );
UpdateWindow( newWind );
可見,創(chuàng)建窗口用CreateWindowEx這個(gè)API函數(shù),它的第一個(gè)參數(shù)是擴(kuò)展樣式,我們這里不設(shè)置擴(kuò)展樣式,所以傳遞0L,第二個(gè)參數(shù)就是窗口類的名字,我們這里指定我們上面已經(jīng)注冊(cè)了的那個(gè)名叫MyWindowClass的窗口類,第三個(gè)參數(shù)是窗口的標(biāo)題,隨便設(shè)置,第四個(gè)參數(shù)是窗口的樣式,我們這里設(shè)置的是WS_OVERLAPPEDWINDOW,一般主窗口都用這個(gè)樣式,就是有化,最小化框,有標(biāo)題欄,有系統(tǒng)菜單。。具體的可以參見MSDN,第五個(gè),六個(gè),七個(gè),八個(gè)參數(shù)分別指定窗口的初始坐標(biāo)和長(zhǎng)寬,第九個(gè)參數(shù)指定父窗口是哪個(gè),這里沒有父窗口,所以傳遞NULL,第十個(gè)參數(shù)指定菜單的句柄,我們這里不設(shè)置菜單,所以傳遞NULL,第十一個(gè)是應(yīng)用程序句柄,用WinMain傳遞進(jìn)來的那個(gè)hInstance參數(shù),第十二個(gè)參數(shù)表示額外數(shù)據(jù),不設(shè)置,所以為NULL。
這個(gè)API函數(shù)有點(diǎn)復(fù)雜,不過用熟悉了也就不覺得了。這樣我們就創(chuàng)建了一個(gè)窗口,返回值是一個(gè)窗口的句柄,如果是NULL的話,說明創(chuàng)建窗口失敗了,如果不是NULL的話,說明成功了。
ShowWindow和UpdateWindow,參數(shù)就是剛才創(chuàng)建成功的那個(gè)窗口的句柄,至于ShowWindow的第二個(gè)參數(shù)是指顯示的類型,是化顯示呢還是最小化顯示呢,不過在程序中第一次調(diào)用ShowWindow必須使用WinMain所傳遞進(jìn)來的參數(shù)的第四個(gè)參數(shù)的值。這是MSDN上說的~
窗口創(chuàng)建成功了,下面一步是消息循環(huán)了,消息循環(huán)說起來復(fù)雜,其實(shí)代碼挺簡(jiǎn)單的,而且基本格式固定,如下:
//消息循環(huán)
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
看到了嗎? 一直在一個(gè)循環(huán)里面,一直調(diào)用GetMessage,只要GetMessage所取得的消息不是WM_QUIT的話,那么GetMessage的返回值就不是0,那么循環(huán)就一直進(jìn)行。在循環(huán)內(nèi)部,將GetMessage取得的消息傳遞給TranslateMessage和DispatchMessage兩個(gè)API函數(shù)進(jìn)行處理.其中DispatchMessage就是將消息發(fā)送給了對(duì)應(yīng)的窗口的窗口消息處理函數(shù)進(jìn)行處理。至于TranslateMessage呢,則進(jìn)行一些消息的轉(zhuǎn)換,可以先不深究。
最后就是編寫窗口消息處理函數(shù)的代碼了,你需要處理那些消息,那么你就編寫處理那些消息的代碼,對(duì)于你不處理的消息,則統(tǒng)統(tǒng)交給一個(gè)叫DefWindowProc的API函數(shù)進(jìn)行默認(rèn)的處理。
LRESULT CALLBACK WinMessageProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch ( msg )
{
case WM_DESTROY:
{
PostQuitMessage( 0 );
break;
}
default:
return DefWindowProc( hwnd, msg, wParam, lParam );
}
return 0;
}
這里我們只處理了WM_DESTROY這個(gè)消息,這個(gè)消息是在窗口被銷毀的時(shí)候發(fā)送給窗口消息處理函數(shù)的,在窗口處理函數(shù)中,我們判斷這個(gè)消息是不是WM_DESTROY,如果是,就調(diào)用PostQuitMessage這個(gè)API函數(shù),如果是其他消息,我們就不管,將參數(shù)全部傳遞給DefWindowProc這個(gè)函數(shù)進(jìn)行處理。
而PostQuitMessage這個(gè)API函數(shù)的功能就是發(fā)送一個(gè)WM_QUIT的消息。而我們前面說到過, 在消息循環(huán)中GetMessage一旦取得WM_QUIT這個(gè)消息,就返回值為0,那么消息循環(huán)也就結(jié)束了,進(jìn)而整個(gè)程序也就結(jié)束了,如果在這里我們處理WM_DESTORY函數(shù),但是不調(diào)用PostQuitMessage,那么結(jié)果會(huì)怎樣呢,讀者朋友們思考一下~~
好了,到這里,這個(gè)什么功能也沒有的SDK程序也就完了,它只顯示一個(gè)帶有標(biāo)題欄的可化,最小化的窗口,除了能夠關(guān)閉它,你幾乎不能進(jìn)行其他任何操作,因?yàn)槲覀兂颂幚泶翱阡N毀這個(gè)消息,其他任何消息我們都沒處理。