




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Windows編程基礎(chǔ)基于Windows的編程方式有兩種。一種是使用Windows的API(Application Programming Interface,應(yīng)用程序編程接口)函數(shù),通常用C/C+語言按相應(yīng)的程序框架進(jìn)行編程。這些程序框架往往就程序應(yīng)用提供相應(yīng)的文檔、范例和軟件開發(fā)工具包(Software Development Kit,SDK),所以這種編程方式有時(shí)又稱為SDK方式。另一種是使用“封裝”方式,例如Visual C+的MFC方式,它是將SDK中的絕大多數(shù)函數(shù)、數(shù)據(jù)等按C+“類”的形式進(jìn)行封裝,并提供相應(yīng)的應(yīng)用程序框架和編程操作。事實(shí)上,無論是哪種編程方式,人們最關(guān)心的內(nèi)容有三
2、個(gè):一是程序入口,二是窗口、資源等的創(chuàng)建和使用,三是鍵盤、鼠標(biāo)等所產(chǎn)生的事件或消息的接收和處理。本章就來討論這些內(nèi)容。1.1 從main到WinMain學(xué)習(xí)編程往往從簡單的例子入手,例如一個(gè)C程序常有下列簡單的框架代碼:#include int main() printf(Hello World!n);/* 輸出 */ return 0;/* 指定返回值 */事實(shí)上,該程序已包括C程序中最常用的#include指令、必須的程序入口main函數(shù)、庫函數(shù)printf調(diào)用和return語句。由于此程序是在早期的DOS(Disk Operating System,磁盤操作系統(tǒng))環(huán)境的字符模型下運(yùn)行的,
3、因而printf函數(shù)所輸出的都是字符流,也就是說,它在屏幕上輸出一行文本“Hello World!”。在Windows環(huán)境下,這里的屏幕就由控制臺窗口來兼作,而基于Windows的上述C程序代碼框架肯定是有所不同的。特別地,由于目前所在的Windows環(huán)境基本上都是32位,所以這里的Windows程序平臺就是Win32,Windows編程可直接理解為是Win32編程。1 / 281.1.1 Windows等價(jià)程序等價(jià)的Windows程序可以寫成:HelloMsg.c #include int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPre
4、vInstance, PSTR szCmdLine, int nCmdShow) MessageBox (NULL, TEXT(Hello, World!), TEXT(Hello), 0) ; return 0 ;在深入剖析上述程序之前,先來看一看在Visual C+ 6.0中的編輯、連接和運(yùn)行的 過程: 圖1.1 “每日提示”對話框 選擇“開始”“程序”Microsoft Visual Studio 6.0 Microsoft Visual C+ 6.0,運(yùn)行Visual C+ 6.0。第一次運(yùn)行時(shí),將顯示如圖1.1所示的“每日提示”對話框。單擊“下一條”按鈕,可看到有關(guān)各種操作的提示。如
5、果在“啟動時(shí)顯示提示”復(fù)選框中單擊鼠標(biāo),去除復(fù)選框的選中標(biāo)記“”,那么下一次運(yùn)行Visual C+ 6.0,將不再出現(xiàn)此對話框。單擊“關(guān)閉”按鈕關(guān)閉此對話框,進(jìn)入Visual C+ 6.0開發(fā)環(huán)境。 選擇“文件”“新建”菜單命令,打開應(yīng)用程序向?qū)?,顯示出“新建”對話框,如圖1.2所示。選擇“工程”選項(xiàng)卡,從列表框中選中Win32 Application(Win32 應(yīng)用程序)項(xiàng)(圖1.2中的標(biāo)記1)。 單擊“位置”編輯框右側(cè)的“瀏覽”按鈕(圖1.2中的標(biāo)記2),從彈出的 “選擇目錄”對話框指定項(xiàng)目所在的文件夾,如圖1.3所示(圖中的數(shù)字標(biāo)記表示最經(jīng)常 的操作次序,下同)。單擊“確定”按鈕,退出
6、“選擇目錄”對話框,回到 “新建”對話框中。需要說明的是,為了便于程序的管理和查找,本書所涉及的程序均放入Visual C+ 6.0的工作文件夾“Visual C+程序”中,第1章程序放入子文件夾“第1章”中,第2章程序放入子文件夾“第2章”,依此類推。 在“新建”對話框的“工程名稱”編輯框(圖1.2中的標(biāo)記3)中,輸入項(xiàng)目名稱Ex_HelloMsg,保留“平臺”下Win32復(fù)選框的默認(rèn)“選中”狀態(tài),單擊“確定”按鈕進(jìn)入下一步。 出現(xiàn)Win32 Application向?qū)У摹安襟E1共1步”對話框,從中可選擇要創(chuàng)建的應(yīng)用程序類型:“一個(gè)空工程”、“一個(gè)簡單的Win32程序”和“一個(gè)典型的Hell
7、o World! 程序”,如圖1.4所示。它們的區(qū)別在于:“一個(gè)空工程”僅創(chuàng)建Win32應(yīng)用程序文件框架,不含任何代碼;“一個(gè)簡單的Win32程序”是在“一個(gè)空工程”基礎(chǔ)上添加了程序框架(有入口函數(shù)、#include指令等);“一個(gè)典型的Hello World!程序”在“一個(gè)簡單的Win32程序”基礎(chǔ)上增加了MessageBox函數(shù)調(diào)用,用來輸出“Hello World!”。 圖1.2 “新建”對話框“工程”選項(xiàng)卡 圖1.3 “選擇目錄”對話框 選中“一個(gè)空工程”,單擊“完成”按鈕,彈出“新建工程信息”對話框,如圖1.5所示。單擊“確定”按鈕,系統(tǒng)將按前面的選擇自動創(chuàng)建此應(yīng)用程序。 圖1.4
8、應(yīng)用程序的向?qū)υ捒?圖1.5 “新建工程信息”對話框 再次選擇“文件”“新建”菜單命令,Visual C+將打開“新建”對話框并自動切換到“文件”選項(xiàng)卡,如圖1.6所示。在左側(cè)的文件類型列表中選中C+ Source File(C+源文件),在右側(cè)的“文件名”編輯框中輸入“HelloMsg.c”或輸入“HelloMsg.cpp”(文件擴(kuò)展名也可不輸入,系統(tǒng)會自動添加cpp擴(kuò)展名,cpp是C Plus Plus的縮寫,是C+的 意思)。 單擊“確定”按鈕,系統(tǒng)將在創(chuàng)建的Win32項(xiàng)目工程Ex_HelloMsg中創(chuàng)建并添加一個(gè)新的文件HelloMsg.c,同時(shí)打開該文件窗口?,F(xiàn)在可以在HelloM
9、sg.c中輸入前面例HelloMsg.c中的代碼了。輸完后,單擊編譯工具條上的“生成工具”按鈕或直接按F7鍵,系統(tǒng)開始對Ex_HelloMsg項(xiàng)目工程中的文件進(jìn)行編譯、連接,同時(shí)在輸出窗口中觀察出現(xiàn)的內(nèi)容,當(dāng)出現(xiàn)Ex_HelloMsg.exe-0 error(s), 0 warning(s)表示Ex_HelloMsg.exe可執(zhí)行文件已經(jīng)正確無誤地生成了。同時(shí)也可看到在文檔窗口中所有代碼的顏色都發(fā)生改變,這是Visual C+ 6.0的文本編輯器所具有的語法顏色功能(綠色表示注釋,藍(lán)色表示關(guān)鍵字等)。 單擊編譯工具條上的“運(yùn)行工具”按鈕或直接按Ctrl+F5鍵,就可以運(yùn)行剛剛生成的Ex_Hel
10、loMsg.exe,結(jié)果如圖1.7所示。單擊“確定”按鈕,Hello對話框退出。 圖1.6 創(chuàng)建并添加程序文件 圖1.7 開發(fā)環(huán)境和運(yùn)行結(jié)果1.1.2 頭文件HelloMsg.c是一個(gè)#include預(yù)處理指令開始,實(shí)際上在用C/C+編寫的Windows應(yīng)用程序的頭部都可以看到這樣的指令:#include 頭文件Windows.h是最主要的包含頭文件,它還包含了其他一些Windows頭文件。 例如:windef.h:基本類型定義winbase.h:內(nèi)核函數(shù)wingdi.h:用戶接口函數(shù)winuser.h:圖形設(shè)備接口函數(shù)這些頭文件定義了Windows的所有數(shù)據(jù)類型、函數(shù)調(diào)用、數(shù)據(jù)結(jié)構(gòu)和符號常量
11、,它們是Windows應(yīng)用程序文檔中的一個(gè)重要部分。1.1.3 程序入口函數(shù)在C/C+程序中,其入口函數(shù)都是main。但在Windows程序中,這個(gè)入口函數(shù)由WinMain來代替。該函數(shù)是在winbase.h中聲明的,其原型如下:intWINAPIWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd);可以看出,這個(gè)WinMain函數(shù)除了形參名、個(gè)數(shù)與main函數(shù)不同外,類型名也有了新的變化。下面就來分析: WinMain函數(shù)被聲明成為返回一個(gè)int值,同時(shí)WinMain函數(shù)名前還有WI
12、NAPI標(biāo)識符的修飾。WINAPI是一種“調(diào)用約定”宏,它在windef.h中有如下定義:#define WINAPI _stdcall所謂“調(diào)用約定”,就是指程序生成機(jī)器碼后,函數(shù)調(diào)用的多個(gè)參數(shù)是按怎樣的次 序來傳遞,同時(shí)函數(shù)調(diào)用結(jié)束后堆棧由誰來恢復(fù),以及編譯器對函數(shù)名的修飾約定等的 協(xié)議。函數(shù)調(diào)用約定“協(xié)議”有許多,其中由WINAPI宏指定的_stdcall是一個(gè)常見的協(xié)議,內(nèi)容包括:參數(shù)從右向左壓入堆棧;函數(shù)自身修改堆棧;機(jī)器碼中的函數(shù)名前面自動加下劃線,而函數(shù)后面接符號和參數(shù)的字節(jié)數(shù)。特別地,Visual C+的MFC方式卻采用了_cdecl調(diào)用約定:參數(shù)從右向左壓入堆棧;傳遞參數(shù)的內(nèi)
13、存棧由調(diào)用者來維護(hù)(正因?yàn)槿绱丝蓪?shí)現(xiàn)變參函數(shù));機(jī)器碼中的函數(shù)名只在前面自動加下劃線。 WinMain函數(shù)的第一個(gè)和第二個(gè)參數(shù)都是HINSTANCE(實(shí)例句柄)類型。HINSTANCE中,H表示Handle,是“句柄”的意思。在Windows編程中,句柄是一個(gè)應(yīng)用程序用來識別某些資源、狀態(tài)、模塊等的數(shù)字。由于句柄唯一標(biāo)識著對應(yīng)的資源、狀態(tài)、模塊等,因而使用句柄就是使(調(diào))用相應(yīng)的資源、狀態(tài)、模塊。當(dāng)應(yīng)用程序運(yùn)行多次時(shí),每一次都是應(yīng)用程序的“實(shí)例”。由于同一個(gè)應(yīng)用程序的所有實(shí)例都共享著應(yīng)用程序的資源,因而程序通過檢查hPrevInstance參數(shù)就可確定自身的其他實(shí)例是否正在運(yùn)行。 WinMai
14、n函數(shù)的第三個(gè)參數(shù)lpCmdLine用來指定程序的命令行,其參數(shù)類型為LPSTR。但在HelloMsg.c中,卻將其改為PSTR。這兩種數(shù)據(jù)類型都是合法的,也都是指向字符串的指針類型。其中的STR是“STRING,字符串”的含義,是指以0結(jié)尾的字符串,LP前綴表示“長指針”,在Win32中它與“P”前綴表示的“指針”含義相同。 WinMain函數(shù)的第四個(gè)參數(shù)nShowCmd用來指定程序最初顯示的方式,它可以是正常、最大化或最小化來顯示程序窗口??v觀上述參數(shù)和類型名可以發(fā)現(xiàn)它們的命名規(guī)則:l C/C+的類型名仍保留其小寫,但新的類型都是用大寫字母來命名。l 參數(shù)名(變量名)都是采用“匈牙利表示法
15、”的命名規(guī)則來定義的。它的主要方法是將變量名前后加上表示“類型”和“作用”的“前綴(小寫)”,而變量名本身由“狀態(tài)”、“屬性”和“含義”等幾個(gè)部分組成,每一個(gè)部分的名稱可以是全稱,也可以是縮寫,但通常只有第一個(gè)字母是大寫。例如,hPrevInstance則是由前綴h(表示“句柄”類型)+狀態(tài)Prev(表示“以前的”)+屬性Instance(表示“實(shí)例”)組成的。1.1.4 MessageBox函數(shù)MessageBox是一個(gè)Win32 API函數(shù),用來彈出一個(gè)對話框窗口,顯示短信息。該函數(shù)具有下列原型:int MessageBox( HWND hWnd, LPCTSTR lpText, LPCT
16、STR lpCaption, UINT uType);其中,第一個(gè)參數(shù)hWnd用來指定父窗口句柄,即對話框所在的窗口句柄。第二、三個(gè)參數(shù)分別用來指定顯示的消息內(nèi)容(lpText)和對話框窗口的標(biāo)題(lpCaption),最后一個(gè)參數(shù)用來指定在對話框中顯示的預(yù)定義的按鈕和圖標(biāo)標(biāo)識,它們是在winuser.h定義的一組以MB_開始的常數(shù)組合。例如,下面是在HelloMsg.c中改變MessageBox的第四個(gè)參數(shù)。#include int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, in
17、t nCmdShow) MessageBox (NULL, TEXT(Hello, World!), TEXT(Hello), MB_ICONQUESTION | MB_ABORTRETRYIGNORE ) ; return 0 ;圖1.8 第四個(gè)參數(shù)的作用程序運(yùn)行后,結(jié)果如圖1.8所示??梢?,MB_ICONQUESTION 用來指定在對話框中顯示圖標(biāo),而MB_ABORTRETRYIGNORE用來指定“終止”、“重試”和“忽略”按鈕,類似這樣的預(yù)定義標(biāo)識還有很多,在以后討論到MFC中的CWnd:MessageBox函數(shù)時(shí)還要討論,故這里不再贅述。在程序HelloMsg.c中,調(diào)用Message
18、Box的實(shí)參中還涉及TEXT宏。在Windows編程中,TEXT宏是用來對UNICODE編碼的字符串的支持。UNICODE是使用兩個(gè)字節(jié)表示一個(gè)字符,這樣單字節(jié)的ANSI字符和雙字節(jié)的“漢字”的表示就統(tǒng)一起來了。在程序中使用TEXT文本,無論在何Windows環(huán)境下均可顯示正確的內(nèi)容,而不會出現(xiàn)亂碼的情形。另外,還有_TEXT 和_T宏等,在Visual C+中,它們的作用是等同的。1.2 窗口和消息MessageBox是通過創(chuàng)建的默認(rèn)“窗口”來顯示簡單的信息:窗口標(biāo)題、一行或多行文本、圖標(biāo)和按鈕等。在Windows環(huán)境中,一個(gè)“窗口”就是屏幕上的一個(gè)矩形區(qū)域,它接收用戶的輸入,并以文本或圖形
19、方式來顯示內(nèi)容。事實(shí)上,“窗口”就是用戶操作的區(qū)域界面,在編程中除創(chuàng)建等操作外,還要處理用戶輸入、窗口本身事件所產(chǎn)生的“消息”。1.2.1 程序框架代碼為了能處理上述兩個(gè)部分的內(nèi)容:窗口創(chuàng)建和消息處理,Windows提供了相應(yīng)的程序框架,如下面的例子。HelloWin.c #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);/ 窗口過程int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdSho
20、w) HWND hwnd ;/ 窗口句柄 MSG msg ;/ 消息 WNDCLASSwndclass ;/ 窗口類 wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCurso
21、r (NULL, IDC_ARROW) ; wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = HelloWin;/ 窗口類名 if (!RegisterClass (&wndclass)/ 注冊窗口 MessageBox (NULL, 窗口注冊失??!, HelloWin, 0) ; return 0 ; / 創(chuàng)建窗口 hwnd = CreateWindow (HelloWin, / 窗口類名 我的窗口,/ 窗口標(biāo)題 WS_O
22、VERLAPPEDWINDOW, / 窗口樣式 CW_USEDEFAULT, / 窗口最初的 x 位置 CW_USEDEFAULT, / 窗口最初的 y 位置 480, / 窗口最初的 x 大小 320, / 窗口最初的 y 大小 NULL, / 父窗口句柄 NULL,/ 窗口菜單句柄 hInstance, / 應(yīng)用程序?qū)嵗浔?NULL) ; / 創(chuàng)建窗口的參數(shù) ShowWindow (hwnd, nCmdShow) ;/ 顯示窗口 UpdateWindow (hwnd) ;/ 更新窗口,包括窗口的客戶區(qū) / 進(jìn)入消息循環(huán):當(dāng)從應(yīng)用程序消息隊(duì)列中檢取的消息是WM_QUIT時(shí),則退出循環(huán) wh
23、ile (GetMessage (&msg, NULL, 0, 0) TranslateMessage (&msg) ;/ 轉(zhuǎn)換某些鍵盤消息 DispatchMessage (&msg) ;/ 將消息發(fā)送給窗口過程,這里是WndProc return msg.wParam ;LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)HDChdc;PAINTSTRUCTps;RECTrc;switch (message)case WM_CREATE:/ 窗口創(chuàng)建產(chǎn)生的消息 return 0 ;
24、case WM_PAINT:hdc= BeginPaint( hwnd, &ps );GetClientRect( hwnd, &rc );/ 獲取窗口客戶區(qū)大小DrawText( hdc, TEXT(Hello Windows!), -1, &rc, DT_SINGLELINE | DT_CENTER |DT_VCENTER );EndPaint( hwnd, &ps ); return 0 ; case WM_DESTROY:/ 當(dāng)窗口關(guān)閉時(shí)產(chǎn)生的消息PostQuitMessage (0) ;return 0 ; return DefWindowProc (hwnd, message, w
25、Param, lParam) ; / 執(zhí)行默認(rèn)的消息處理創(chuàng)建并運(yùn)行上述程序時(shí),先創(chuàng)建一個(gè)Ex_HelloWin“空工程”,然后再創(chuàng)建并添加新的源文件hellowin.c,輸入上述代碼,然后編連和運(yùn)行,結(jié)果如圖1.9所示(里面的框是加上去的,它的區(qū)域叫“客戶區(qū)”)。雖然與Ex_HelloMsg示例相比,Ex_HelloWin要復(fù)雜得多,但總可以將其分解成是兩個(gè)基本函數(shù)的程序結(jié)構(gòu)。一個(gè)就是前面所討論的WinMain函數(shù),另一個(gè)是用戶定義的窗口過程函數(shù)WndProc。窗口過程函數(shù)WndProc用來接收和處理各種不同的消息。圖1.9 hellowin.c運(yùn)行結(jié)果1.2.2 注冊窗口類在為程序創(chuàng)建窗口之
26、前,必須首先調(diào)用創(chuàng)建RegisterClass注冊應(yīng)用程序的窗口類。該函數(shù)只要一個(gè)參數(shù),即一個(gè)指向類型為WNDCLASS的結(jié)構(gòu)指針。它包含了一個(gè)窗口的基本屬性,如窗口邊框、窗口標(biāo)題欄文字、窗口大小和位置、鼠標(biāo)、背景色、處理窗口消息函數(shù)的名稱等。事實(shí)上,注冊的過程也就是將這些屬性告訴系統(tǒng),然后再調(diào)用CreateWindow函數(shù)創(chuàng)建出窗口。WNDCLASS結(jié)構(gòu)具有下列原型:typedef struct UINT style;/ 窗口的風(fēng)格 WNDPROC lpfnWndProc;/ 指定窗口的消息處理函數(shù)的窗口過程函數(shù) int cbClsExtra;/ 指定分配給窗口類結(jié)構(gòu)之后的額外字節(jié)數(shù) int
27、 cbWndExtra;/ 指定分配給窗口實(shí)例之后的額外字節(jié)數(shù) HINSTANCE hInstance;/ 指定窗口過程所對應(yīng)的實(shí)例句柄 HICON hIcon;/ 指定窗口的圖標(biāo) HCURSOR hCursor;/ 指定窗口的鼠標(biāo)指針 HBRUSH hbrBackground;/ 指定窗口的背景畫刷 LPCTSTRlpszMenuName;/ 窗口的菜單資源名稱 LPCTSTR lpszClassName;/ 該窗口類的名稱 WNDCLASS, *PWNDCLASS;從中可以看出:該結(jié)構(gòu)有10個(gè)域(成員),其中第一個(gè)域style表示窗口類的風(fēng)格,它往往是由一些基本的預(yù)定義風(fēng)格通過位的“或”操
28、作(操作符位“|”)組合而成的。例如,在HelloWin.c中,有:WNDCLASSwndclass ;/ 窗口類wndclass.style = CS_HREDRAW | CS_VREDRAW ;wndclass.lpfnWndProc = WndProc ;wndclass.cbClsExtra = 0 ;wndclass.cbWndExtra = 0 ;wndclass.hInstance = hInstance ;wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;wndclass.hCursor = LoadCursor (NULL,
29、 IDC_ARROW) ;wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;wndclass.lpszMenuName = NULL;wndclass.lpszClassName = HelloWin;/ 窗口類名可以看到,wndclass.style被設(shè)為CS_VREDRAW | CS_HREDRAW,表示只要窗口的高度或?qū)挾劝l(fā)生變化,都會重畫整個(gè)窗口。第二個(gè)域lpfnWndProc的值為WndProc。表明該窗口類的消息處理函數(shù)是WndProc函數(shù)。這里,可簡單直接地輸入消息處理(窗口過程)函數(shù)的函數(shù)名即可。接下來的cbClsEx
30、tra和cbWndExtra在大多數(shù)情況下都會設(shè)為0。然后的hInstance成員,給它的值是由WinMain傳來的應(yīng)用程序的實(shí)例句柄,表明該窗口與該實(shí)例是相關(guān)聯(lián)的。事實(shí)上,只要是注冊窗口類,該成員的值始終是該程序的實(shí)例句柄。下面的hIcon,是要給這個(gè)窗口指定一個(gè)圖標(biāo),LoadIcon (NULL, IDI_APPLICATION)就是調(diào)用系統(tǒng)內(nèi)部預(yù)先定義好的標(biāo)識符為IDC_APPLICATION的圖標(biāo)作為該窗口的圖標(biāo)。同樣,LoadCursor (NULL, IDC_ARROW)就是調(diào)用預(yù)定義的箭型鼠標(biāo)指針。hbrBackground域用來定義窗口的背景畫刷顏色,也就是該窗口的背景色。調(diào)用
31、GetStockObject (WHITE_BRUSH)可以獲得系統(tǒng)內(nèi)部預(yù)先定義好的白色畫刷作為窗口的背景色。這里L(fēng)oadIcon、LoadCursor、GetStockObject等都是Windows的API函數(shù),在程序中可直接 調(diào)用。lpszMenuName域的值若為NULL,則表示該窗口將沒有菜單。否則,需要指定表示菜單資源的字符串。 WNDCLASS結(jié)構(gòu)的最后一個(gè)域lpszClassName是要給這個(gè)窗口類起一個(gè)唯一的名稱,因?yàn)閃indows操作系統(tǒng)中有許許多多的窗口類,必須用一個(gè)獨(dú)一無二的名稱來代表它們。通常,可以用程序名來直接作為這個(gè)窗口類的名稱,它在創(chuàng)建窗口的CreateWind
32、ow函數(shù)中用到。1.2.3 創(chuàng)建和顯示窗口當(dāng)窗口類注冊完畢之后,并不會有窗口顯示出來,因?yàn)樽缘倪^程僅僅是為創(chuàng)建窗口所做的準(zhǔn)備工作。實(shí)際創(chuàng)建一個(gè)窗口是通過調(diào)用CreateWindow函數(shù)完成的。窗口類中已經(jīng)預(yù)先定義了窗口的一般屬性,而CreateWindow中的參數(shù)可以進(jìn)一步指定一個(gè)窗口的更具體的屬性,在HelloWin.c程序中,是用下列調(diào)用CreateWindow函數(shù)的代碼來創(chuàng)建窗 口的: hwnd = CreateWindow (HelloWin, / 窗口類名,要與注冊時(shí)指定的相同 我的窗口,/ 窗口標(biāo)題 WS_OVERLAPPEDWINDOW, / 窗口樣式 CW_USEDEFAUL
33、T, / 窗口最初的 x 位置 CW_USEDEFAULT, / 窗口最初的 y 位置 480, / 窗口最初的 x 大小 320, / 窗口最初的 y 大小 NULL, / 父窗口句柄 NULL,/ 窗口菜單句柄 hInstance, / 應(yīng)用程序?qū)嵗浔?NULL) ; / 創(chuàng)建窗口的參數(shù)CreateWindow函數(shù)的第一個(gè)參數(shù)是創(chuàng)建該窗口所使用的窗口類的名稱,注意這個(gè)名稱應(yīng)與前面所注冊的窗口類的名稱一致。第三個(gè)參數(shù)為創(chuàng)建的窗口的風(fēng)格,它們通常是一些預(yù)定義風(fēng)格的“|”組合。其中,WS_OVERLAPPEDWINDOW表示創(chuàng)建一個(gè)層疊式窗口,有邊框、標(biāo)題欄、系統(tǒng)菜單、最大化和最小化按鈕等。C
34、reateWindow函數(shù)后面的參數(shù)中,仍用到了該應(yīng)用程序的實(shí)例句柄hInstance。如果窗口創(chuàng)建成功,返回值是新窗口的句柄,否則返回NULL。窗口創(chuàng)建后,并不會在屏幕上顯示出來。要能真正把窗口顯示在屏幕上,還得使用ShowWindow函數(shù),其原型如下: BOOL ShowWindow( HWND hWnd, int nCmdShow ); 其中,參數(shù)hWnd指定要顯示得窗口的句柄,nCmdShow表示窗口的顯示方式,這里指定為從WinMain函數(shù)的nCmdShow所傳遞而來的值。由于ShowWindow函數(shù)的執(zhí)行優(yōu)先級不高,所以當(dāng)系統(tǒng)正忙著執(zhí)行其他的任務(wù)時(shí),窗口不會立即顯示出來,此時(shí),調(diào)用
35、UpdateWindow函數(shù)以可以立即顯示窗口。同時(shí),它將會給窗口過程發(fā)出WM_PAINT消息。1.2.4 消息和消息處理1消息循環(huán)在Win32編程中,消息循環(huán)是相當(dāng)重要的一個(gè)概念,看似很難,但使用起來卻是非常簡單。在WinMain函數(shù)的最后,有下列代碼:while (GetMessage (&msg, NULL, 0, 0) TranslateMessage (&msg) ;/ 轉(zhuǎn)換某些鍵盤消息DispatchMessage (&msg) ;/ 將消息發(fā)送給窗口過程,這里是WndProcWindows應(yīng)用程序可以接收以各種形式輸入的信息,這包括鍵盤、鼠標(biāo)動作、計(jì)時(shí)器產(chǎn)生的消息,也可以是其他應(yīng)
36、用程序發(fā)來的消息等。Windows系統(tǒng)自動監(jiān)控所有的輸入設(shè)備,并將其消息放入該應(yīng)用程序的消息隊(duì)列中。GetMessage函數(shù)就是用來從應(yīng)用程序的消息隊(duì)列中按照先進(jìn)先出的原則將這些消息一個(gè)個(gè)地取出來,放進(jìn)一個(gè)MSG結(jié)構(gòu)中去。它的原型如下:BOOL GetMessage( LPMSG lpMsg, / 指向一個(gè)MSG結(jié)構(gòu)的指針,用來保存消息 HWND hWnd, / 指定哪個(gè)窗口的消息將被獲取 UINT wMsgFilterMin,/ 指定獲取的主消息值的最小值 UINT wMsgFilterMax/ 指定獲取的主消息值的最大值);GetMessage函數(shù)用來將獲取的消息復(fù)制到一個(gè)MSG結(jié)構(gòu)中。如
37、果隊(duì)列中沒有任何消息,該函數(shù)將一直空閑直到隊(duì)列中又有消息時(shí)再返回。如果隊(duì)列中已有消息,它將取出一個(gè)后返回。MSG結(jié)構(gòu)包含Windows消息的完整信息,其定義如下:typedef struct HWND hwnd; / 消息發(fā)向的窗口的句柄 UINT message;/ 主消息的標(biāo)識值 WPARAM wParam;/ 附消息值,其具體含義依賴于主消息值 LPARAM lParam;/ 附消息值,其具體含義依賴于主消息值 DWORD time;/ 消息放入消息隊(duì)列中的時(shí)間 POINT pt;/ 消息放入消息隊(duì)列時(shí)的鼠標(biāo)坐標(biāo) MSG, *PMSG;上述結(jié)構(gòu)中的主消息表明了消息的類型,例如,是鍵盤消息
38、還是鼠標(biāo)消息等,附消息的含義則依賴于主消息值,例如,如果主消息是鍵盤消息,那么附消息中則存儲了是鍵盤的哪個(gè)具體鍵的信息。事實(shí)上,GetMessage函數(shù)還可以過濾消息,它的第二個(gè)參數(shù)是用來指定從哪個(gè)窗口的消息隊(duì)列中獲取消息,其他窗口的消息將被過濾掉。如果該參數(shù)為NULL,則GetMessage從該應(yīng)用程序線程的所有窗口的消息隊(duì)列中獲取消息。第三個(gè)和第四個(gè)參數(shù)是用來過濾MSG結(jié)構(gòu)中主消息值的,主消息值在wMsgFilterMin和wMsgFilterMax之外的消息將被過濾掉。如果這兩個(gè)參數(shù)為0,則表示接收所有消息。特別地,當(dāng)且僅當(dāng)GetMessage函數(shù)在獲取到WM_QUIT消息后,將返回0值
39、,于是程序退出消息循環(huán)。TranslateMessage函數(shù)的作用是把虛擬鍵消息轉(zhuǎn)換到字符消息,以滿足鍵盤輸入的需要。DispatchMessage函數(shù)所完成的工作是把當(dāng)前的消息發(fā)送到對應(yīng)的窗口過程中去。2消息處理用于消息處理的函數(shù)又叫窗口過程,在這個(gè)函數(shù)中,不同的消息將用switch語句分配到不同的處理程序中去。Windows的消息處理函數(shù)都有一個(gè)確定的統(tǒng)一方式,即這種函數(shù)的參數(shù)個(gè)數(shù)和類型以及其返回值的類型都有明確的規(guī)定。在HelloWin.c中,WinProc函數(shù)明確處理了3個(gè)消息,分別是WM_CREATE(創(chuàng)建窗口消息)、WM_PAINT(窗口重畫消息)、WM_DESTROY(銷毀窗口消
40、息)。事實(shí)上,應(yīng)用程序發(fā)送到窗口的消息遠(yuǎn)遠(yuǎn)不止以上這幾條,像WM_SIZE、WM_MINIMIZE、WM_MOVE等這樣經(jīng)常使用的消息就有好幾十條。為了減輕編程的負(fù)擔(dān),Windows的API提供了DefWindowProc函數(shù)來處理這些最常用的消息,調(diào)用這個(gè)函數(shù)后,這些消息將按照系統(tǒng)默認(rèn)的方式得到處理。因此,在switch語句中,只需明確處理那些有必要進(jìn)行特別響應(yīng)的消息,把其余的消息交給DefWindowProc函數(shù)來處理,即將消息的控制交由Windows進(jìn)行默認(rèn)處理,這是一種明智的選擇。 3結(jié)束消息循環(huán) 當(dāng)用戶按Alt+F4鍵或單擊窗口右上角的“退出”按鈕,系統(tǒng)就向應(yīng)用程序發(fā)送一條WM_DE
41、STROY的消息。在處理此消息時(shí),調(diào)用了PostQuitMessage函數(shù),該函數(shù)會向窗口的消息隊(duì)列中發(fā)送一條WM_QUIT消息。在消息循環(huán)中,GetMessage函數(shù)一旦檢索到這條消息,就會返回FALSE,從而結(jié)束消息循環(huán),隨后程序也結(jié)束。1.2.5 WM_PAINT消息WM_PAINT是Win32的圖形和文本編程中經(jīng)常使用到的消息。當(dāng)窗口客戶區(qū)的一部分或全部變成“無效”時(shí),則必須 “刷新”重繪,此時(shí)將向程序發(fā)出此消息。那么客戶區(qū)怎么會“無效”呢?在最初窗口創(chuàng)建時(shí),整個(gè)客戶區(qū)都是“無效”的,因?yàn)榇翱谏线€沒有繪制任何東西。所以,在創(chuàng)建窗口時(shí),會發(fā)出第一個(gè)WM_PAINT消息。在HelloWin
42、.c程序中,由于在注冊窗口時(shí),指定了wndclass.style的風(fēng)格為CS_VREDRAW和 CS_HREDRAW,這表明只要窗口的高度或?qū)挾劝l(fā)生變化,就將使整個(gè)窗口“無效”,從而發(fā)出WM_PAINT消息,使得系統(tǒng)重畫整個(gè)窗口。當(dāng)窗口最小化再恢復(fù)為以前的大小時(shí),Windows將令窗口“無效”,并發(fā)出WM_PAINT消息使系統(tǒng)重畫整個(gè)窗口。當(dāng)窗口移至與另一窗口有重疊被遮擋時(shí),Windows也將窗口視為“無效”,發(fā)出WM_PAINT消息以便刷新窗口。在窗口過程函數(shù)WndProc中,WM_PAINT消息處理通??偸菑腂eginPaint函數(shù)開始,而從EndPaint函數(shù)結(jié)束。BeginPaint函
43、數(shù)用來返回指定窗口句柄的設(shè)備描述表句柄,設(shè)備描述表用來將程序與計(jì)算機(jī)外部輸出設(shè)備連接起來。hdc定義的是句柄HDC變量,DrawText等GDI函數(shù)都需要通過這樣的HDC句柄來繪制圖形和文本。EndPaint用來釋放設(shè)備描述表句柄,并使先前無效區(qū)域變?yōu)橛行В瑥亩筗indows不再發(fā)送WM_PAINT消息。PAINTSTRUCT是“繪圖信息結(jié)構(gòu)”,BeginPaint和EndPaint函數(shù)都需要PAINTSTRUCT結(jié)構(gòu)變量作為自己的參數(shù)。需要說明的是,BeginPaint和EndPaint函數(shù)必須成對出現(xiàn),所有GDI函數(shù)的調(diào)用也應(yīng)在這兩個(gè)函數(shù)之間進(jìn)行。DrawText函數(shù)用來在參考矩形內(nèi)使用
44、指定的格式來繪制文本,它的函數(shù)原型如下:int DrawText( HDC hDC, / 繪制設(shè)備的句柄 LPCTSTR lpString, / 要繪制的文本 int nCount, / 文本的字符個(gè)數(shù) LPRECT lpRect, / 參考矩形 UINT uFormat / 文本繪制格式);其中,當(dāng)nCount為1時(shí),表示lpString指定的是以“0”為結(jié)尾的字符串,并自動計(jì)算該字符串的字符個(gè)數(shù)。lpRect是一個(gè)指向RECT類型的“矩形”結(jié)構(gòu)指針,該“矩形”結(jié)構(gòu)含有l(wèi)eft、top、right和bottom 4個(gè)LONG域。為了能在窗口客戶區(qū)中間繪制文本,該函數(shù)的lpRect被填為REC
45、T變量rc的指針,它通過調(diào)用GetClientRect函數(shù),獲取hwnd窗口的客戶區(qū)大小。同時(shí),指定uFormat格式為DT_SINGLELINE(單行輸出)、DT_CENTER(水平居中)和DT_VCENTER(垂直居中)。1.2.6 Windows基本數(shù)據(jù)類型在前面示例和函數(shù)原型中,有一些“奇怪”的數(shù)據(jù)類型,如前面的HINSTANCE和LPSTR等,事實(shí)上,很多這樣的數(shù)據(jù)類型只是一些基本數(shù)據(jù)類型的別名,以方便不同風(fēng)格的程序員使用。表1.1列出了一些在Windows編程中常用的基本數(shù)據(jù)類型;表1.2列出了常用的預(yù)定義句柄,它們的類型均為void *,即一個(gè)32位指針。表1.1 Windows
46、編程中常用的基本數(shù)據(jù)類型Windows所用的數(shù)據(jù)類型對應(yīng)的基本數(shù)據(jù)類型說明BOOLbool布爾值BSTRunsigned short *32位字符指針BYTEunsigned char8位無符號整數(shù)COLORREFunsigned long用作顏色值的32位值DWORDunsigned long32位無符號整數(shù),段地址和相關(guān)的偏移地址LONGlong32位帶符號整數(shù)LPARAMlong作為參數(shù)傳遞給窗口過程或回調(diào)函數(shù)的32位值LPCSTRconst char *指向字符串常量的32位指針LPSTRchar *指向字符串的32位指針LPVOIDvoid *指向未定義類型的32位指針LRESULT
47、long來自窗口過程或回調(diào)函數(shù)的32位返回值UINTunsigned int32位無符號整數(shù)WORDunsigned short16位無符號整數(shù)WPARAMunsigned int當(dāng)做參數(shù)傳遞給窗口過程或回調(diào)函數(shù)的32位值說明:l 這些基本數(shù)據(jù)類型都是用大寫字符來表示的,以與一般C/C+基本數(shù)據(jù)類型相 區(qū)別。l 若數(shù)據(jù)類型的前綴是P或LP,則表示該類型是一個(gè)指針或長指針數(shù)據(jù)類型;若數(shù)據(jù)類型的前綴是U,則表示是無符號數(shù)據(jù)類型。l Windows還提供一些宏來處理上述基本數(shù)據(jù)類型。例如,LOBYTE和HIBYTE分別用來獲取16位數(shù)值中的低位和高位字節(jié),LOWORD和HIWORD分別用來獲取32位
48、數(shù)值中的低位字和高位字,MAKEWORD是將兩個(gè)16位無符號值結(jié)合成一個(gè)32位無符號值。表1.2 Windows編程中常用的句柄類型句柄類型說明HBITMAP保存位圖信息的內(nèi)存域的句柄HBRUSH畫刷句柄續(xù)表句柄類型說明HCURSOR鼠標(biāo)光標(biāo)句柄HDC設(shè)備描述表句柄HFONT字體句柄HICON圖標(biāo)句柄HINSTANCE應(yīng)用程序的實(shí)例句柄HMENU菜單句柄HPALETTE顏色調(diào)色板句柄HPEN在設(shè)備上畫圖時(shí)用于指明線型的筆的句柄HWND窗口句柄1.3 C+的“類”事實(shí)上,前面的Ex_HelloMsg和Ex_HelloWin都是基于Win32 API的C/C+應(yīng)用程序。顯然,隨著應(yīng)用程序的復(fù)雜性增
49、加,C/C+應(yīng)用程序代碼也必然變得復(fù)雜。為了簡化上述編程,Visual C+設(shè)計(jì)了一套基礎(chǔ)類庫(Microsoft Foundation Class Library,MFC)。MFC把Windows編程規(guī)范中的大多數(shù)內(nèi)容封裝成為各種類,使程序員從繁雜的編程中解脫出來,提高了編程和代碼效率。那么,什么是“類”呢?這里就先來討論它。1.3.1 類和對象1類的定義如同C語言的“結(jié)構(gòu)”類型,“類”也是一種復(fù)合的數(shù)據(jù)類型,只不過要更為復(fù)雜一些。在C+中,一個(gè)獨(dú)立“類”的聲明格式一般如下:class / 聲明部分類體private:public:protected:;/ 實(shí)現(xiàn)部分其中,class是類聲明的
50、關(guān)鍵字,class的后面是要聲明的類名。類中的數(shù)據(jù)和函數(shù)都是類的成員,分別稱為數(shù)據(jù)成員和成員函數(shù)。數(shù)據(jù)成員用來描述類狀態(tài)等的屬性,由于數(shù)據(jù)成員常用變量來定義,所以有時(shí)又將這樣的數(shù)據(jù)成員稱為成員變量。成員函數(shù)是用來對數(shù)據(jù)成員進(jìn)行操作的,又稱為方法。注意:類體中最后一個(gè)花括號后面的分號“;”不能省略。類中關(guān)鍵字public、private和protected聲明了類中的成員與類外之間的關(guān)系,稱為訪問權(quán)限。對于public成員來說,它們是公有的,可以在類外訪問。對于private成員來說,它們是私有的,不能在類外訪問,數(shù)據(jù)成員只能由類中的函數(shù)所使用,成員函數(shù)只允許在類中調(diào)用。而對于protected成員來說,它們是受保護(hù)的,具有半公開性質(zhì),可在類中或其子類中訪問(后面還會討論)。成員函數(shù)既可以在類中進(jìn)行定義,也可先在類中聲明函數(shù)原型,然后在類外定義,這種定義又稱為成員函數(shù)的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 鄉(xiāng)村振興戰(zhàn)略下職業(yè)技能培訓(xùn)對鄉(xiāng)村經(jīng)濟(jì)結(jié)構(gòu)調(diào)整的影響報(bào)告
- 808激光脫毛培訓(xùn)課件
- 中國衛(wèi)生監(jiān)督培訓(xùn)課件
- 員工安全操作課件
- 系文宣部培訓(xùn)大會
- 中國傳統(tǒng)節(jié)日課件背景
- 幼師教育案例分享
- 浙大中控培訓(xùn)
- 制作商務(wù)培訓(xùn)
- 企業(yè)法治教育培訓(xùn)
- 圖解“雙均線雙交叉”期貨、股票操作系統(tǒng)課件
- 小學(xué)語文擴(kuò)句、縮句專題
- 農(nóng)村公路安全生命防護(hù)工程施工方案
- (部編版)統(tǒng)編版小學(xué)語文教材目錄(一至六年級上冊下冊齊全)
- 抗滑樁專項(xiàng)的施工組織方案[專家評審]
- 常用彈簧鋼號對照表
- 應(yīng)用回歸分析(第三版)何曉群_劉文卿_課后習(xí)題答案_完整版
- 小學(xué)二年級下冊勞動教案
- 食品安全及衛(wèi)生保證措施
- 60m3臥式液化石油氣儲罐設(shè)計(jì)
- 樹脂的污染及處理
評論
0/150
提交評論