Windows
應(yīng)用程序基本結(jié)構(gòu)
一個(gè)完整的
windos
應(yīng)用程序通常由下面五種類型的文件組成:
1.????????
擴(kuò)展名為
.c/.cpp
的C語(yǔ)言程序源文件
2.????????
擴(kuò)展名為
.h
的頭文件
3.????????
擴(kuò)展名為
.rc
的資源描述文件
4.????????
擴(kuò)展名為
.def
的模塊定義文件
5.????????
擴(kuò)展名為
.mak
的項(xiàng)目文件
前面三種很常見(jiàn)了,不過(guò)后面兩個(gè)就
……
暫時(shí)不管,以后遇見(jiàn)了再說(shuō)。
源程序組成結(jié)構(gòu)
與
console
程序相對(duì)應(yīng),
windows
應(yīng)用程序也有一個(gè)入口函數(shù)
WinMain
,用于完成一系列的定義和初始化工作,并產(chǎn)生消息循環(huán)。消息循環(huán)是整個(gè)程序運(yùn)行的核心。此外,窗口函數(shù)
WndProc
是處理接收到的消息的函數(shù)。其中包含了應(yīng)用程序?qū)Ω鞣N可能接收到的消息的處理過(guò)程。
?
WinMain
函數(shù)的功能:
注冊(cè)窗口類,建立窗口及執(zhí)行其他必要的初始化工作
進(jìn)入消息循環(huán),根據(jù)從應(yīng)用程序消息隊(duì)列接受的消息調(diào)用相應(yīng)的處理過(guò)程。
當(dāng)消息循環(huán)檢測(cè)到
WM_QUIT
消息時(shí)終止程序運(yùn)行。
WinMian
函數(shù)由三個(gè)基本組成部分:函數(shù)說(shuō)明、初始化和消息循環(huán)。
(1)?????
函數(shù)說(shuō)明
int WINAPI WinMain
(
?????? HINSTANCE hThisInst,??????? //
應(yīng)用程序當(dāng)前實(shí)例句柄
?????? HINSTANCE hPrevInst,????????????? //
應(yīng)用程序其它實(shí)例句柄
?????? LPSTR lpszCmdLine,?????????? //
指向程序命令行參數(shù)的指針
?????? Int nCmdShow??????????????????? //
應(yīng)用程序開(kāi)始執(zhí)行時(shí)窗口顯示方式的標(biāo)識(shí)
)
應(yīng)當(dāng)注意到,
windows
程序可能并行的進(jìn)行多次執(zhí)行,因而可能出現(xiàn)同一個(gè)應(yīng)用程序的多個(gè)窗口同時(shí)存在的情況。在
windows
中,每執(zhí)行一次稱其為一個(gè)實(shí)例(
instance
),并使用一個(gè)實(shí)例句柄進(jìn)行唯一的標(biāo)識(shí)。
?
(2)?????
初始化工作包括:窗口類的定義,注冊(cè),創(chuàng)建窗口實(shí)例和顯示窗口四個(gè)部分。
???????????
窗口類的定義
在
windows
程序中,窗口類定義了窗口的形式與功能。窗口類定義通過(guò)給窗口類數(shù)據(jù)結(jié)構(gòu)
WNDCLASS
賦值完成,該數(shù)據(jù)結(jié)構(gòu)中包含窗口類的各種屬性。常用函數(shù)有:
LoadIcon
在程序中加載一個(gè)窗口圖標(biāo)
LoadCursor
向程序加載一個(gè)窗口光標(biāo)
GetStockObject
可以獲取各種系統(tǒng)默認(rèn)資源
???????????
注冊(cè)窗口類
Windows
系統(tǒng)本身提供部分預(yù)定義的窗口類,程序員也可以自定義窗口類。窗口類必須先用函數(shù)
RegisterClass
進(jìn)行注冊(cè)后才能使用。
其形式為:
??? BOOL RegisterClass( &wndClass )
???????????
創(chuàng)建窗口
窗口創(chuàng)建由函數(shù)
CreateWindow
實(shí)現(xiàn),其原型為:
HWND CreateWinodw
(
LPCTSTR lpszClassName,?????????? //
窗口類名,此窗口名必須是已經(jīng)注冊(cè)過(guò)的
LPCTSTR lpszTitile,??????????????????? //
窗口標(biāo)題
DWORD dwStyle,?????????????????????? //
窗口樣式
int x,?????????????????????????????????????????
int y,???????????????????????????????????????????????? //
窗口左上角坐標(biāo)
int nWidth,
int nHeight,???????????????????????????????? //
窗口高寬
HWND hwndParent,??????????????????? //
該窗口父窗口句柄
HMENU hMenu,???????????????????????? //
主菜單句柄
HINSTANCE hInstance,???????????????????? //
當(dāng)前應(yīng)用程序句柄
LPVOID lpParam??????????????????????? //
指向一個(gè)傳遞給窗口參數(shù)值的指針
)
???????????
顯示窗口
窗口類顯示由
ShowWindow
和
UpdateWindow
函數(shù)實(shí)現(xiàn)。
ShowWindow
將窗口顯示在屏幕上,形式為
BOOL ShowWindow( HWND, int )
顯示完窗口后常常使用
UpdateWindow
更新并繪制用戶區(qū),并發(fā)出
WM_PAINT
消息,形式為
UpdateWindow( HWND )
?
(3)?????
消息循環(huán)
Windows
應(yīng)用程序的運(yùn)行以消息為核心。
Windows
將產(chǎn)生的消息放入應(yīng)用程序的消息隊(duì)列中,而應(yīng)用程序的
WinMain
函數(shù)在消息循環(huán)中提取隊(duì)列中的消息,并將其傳遞給窗口函數(shù)的相應(yīng)過(guò)程處理。
消息循環(huán)常見(jiàn)格式為:
MSG?msg;

while
(GetMessage(
&
msg,?NULL,?
0
,?
0
))??????
//
讀取一條消息存放在一個(gè)MSG結(jié)構(gòu)中
{

???????TranslateMessage(
&
msg);???????????????????
//
將消息的虛擬鍵轉(zhuǎn)換為字符信息
???????DispatchMessage(
&
msg);???????????????????
//
將參數(shù)指向的消息傳送到指定的窗口函數(shù)
}
只有當(dāng)
GetMessage
函數(shù)返回
0
值,即檢索到
WM_QUIT
消息時(shí),程序結(jié)束退出。
?
窗口函數(shù)
窗口函數(shù)的主體是消息處理語(yǔ)句,由一系列
case
語(yǔ)句組成。程序員只需要根據(jù)窗口可能收到的消息在
case
語(yǔ)句中編寫相應(yīng)的處理程序段即可。一般形式如下:
LRESULT?CALLBACK?WndProc?(HWND?hwnd,?UINT?message,?

WPARAM?wParam,?LPRARM?lParam)


{

???????…

swithch(message)


{

???????
case
?…

??????????????…

???????
case
?WM_DESTROY:

??????????????PostQuitMessage(
0
);

???????
default
:

??????????????
return
?DefWindowProc(hwnd,?message,?wParam,?lParam);

}
???????
return
?
0
;

}
?
?
???????????
應(yīng)用程序舉例
Hello Windows API
:
#include?
windows.h
>
?

LRESULT?CALLBACK?WndProc(HWND?hwnd,?UINT?message,?

???????????????????????????????????????????WPARAM?wParam,?LPARAM?lParam)


{

???????
switch
(message)


???????
{

???????
case
?WM_DESTROY:

??????????????PostQuitMessage(
0
);

??????????????
break
;

???????
default
:

??????????????
return
?DefWindowProc(hwnd,?message,?wParam,?lParam);

???????}
???????
return
?
0
;

}
?

int
?WINAPI?WinMain(HINSTANCE?hInstance,

?????????????????????HINSTANCE?hPrevInstance,

?????????????????????LPSTR?????lpCmdLine,

?????????????????????
int
???????nCmdShow)


{

???????HWND?hwnd;

???????MSG?msg;

???????WNDCLASS?wndclass;

???????
char
?lpszClassName[]?
=
?
"
hello
"
;

???????
char
?lpszTitle[]?
=
?
"
Hello?Windows?API
"
;

???????
//
------------窗口類的定義
???????wndclass.style?
=
?
0
;

???????wndclass.lpfnWndProc?
=
?WndProc;

???????wndclass.cbClsExtra?
=
?
0
;
//
類無(wú)擴(kuò)展
???????wndclass.cbWndExtra?
=
?
0
;
//
窗口無(wú)擴(kuò)展
???????wndclass.hInstance?
=
?hInstance;
//
當(dāng)前句柄實(shí)例
???????wndclass.hIcon?
=
?LoadIcon(NULL,IDI_APPLICATION);
//
最小化為默認(rèn)圖標(biāo)
???????wndclass.hCursor?
=
?LoadCursor(NULL,IDC_ARROW);
//
箭頭光標(biāo)
???????wndclass.hbrBackground?
=
?(HBRUSH)GetStockObject(BLACK_BRUSH);
//
黑色背景
???????wndclass.lpszMenuName?
=
?NULL;
//
無(wú)菜單
???????wndclass.lpszClassName?
=
?lpszClassName;
//
窗口類名

?

???????
//
------------窗口類注冊(cè)
???????
if
(
!
RegisterClass(
&
wndclass))


???????
{

??????????????MessageBeep(
0
);
//
如果失敗發(fā)出警告音
??????????????
return
?FALSE;

???????}
???????
//
創(chuàng)建窗口
???????hwnd?
=
?CreateWindow(lpszClassName,?lpszTitle,

??????????????????????????????????????????WS_SYSMENU,
//
窗口風(fēng)格
??????????????????????????????????????????CW_USEDEFAULT,
//
左上角坐標(biāo)為默認(rèn)值
??????????????????????????????????????????CW_USEDEFAULT,

??????????????????????????????????????????
400
,
//
窗口高寬
??????????????????????????????????????????
300
,

??????????????????????????????????????????NULL,
//
無(wú)父窗口
??????????????????????????????????????????NULL,
//
無(wú)主菜單
??????????????????????????????????????????hInstance,
//
創(chuàng)建窗口程序的當(dāng)前句柄
??????????????????????????????????????????NULL);
//
不使用該值
???????ShowWindow(hwnd,?nCmdShow);

???????UpdateWindow(hwnd);

?

???????
//
-------------消息循環(huán)
???????
while
(GetMessage(
&
msg,?NULL,?
0
,?
0
))


???????
{

??????????????TranslateMessage(
&
msg);

??????????????DispatchMessage(
&
msg);

???????}
?

???????
return
?msg.wParam;

}