遊戲編程之三 DirectX SDK簡介

` 第三章 DirectX  SDK簡介 第一節 關於DirectX SDK Microsoft DirectX提供了一套很是優秀的應用程序接口,包含了設計高性能、實時應用程序的源代碼。DirectX技術將幫助您建構下一代的電腦遊戲和多媒體應用程序。它的內容包括了DirectDraw、DirectSound、DirectPlay、Direct3D和DirectInput等部分,它們分別主要應用在圖形程序、聲音程序等方面。 因爲DirectX,使在Windows下運行應用程序的性能能夠與在DOS或遊戲平臺下運行的應用程序性能相媲美,甚至超過它們。它將爲您的Windows遊戲開發提供一個具備魯棒性的、標準化的操做環境。 DirectX包括兩部分:運行期部分(Runtime)和SDK。在DirectX開發時,這兩部分都要用到,但在DirectX應用程序運行時只用運行期部分。在Windows NT 4.0及以上版本中含有DirectX運行期部分,Win95則沒有。但Win95能夠很容易得到DirectX運行期部分。而Windows NT 4.0之前的版本不能運行DirectX程序。許多基於DirectX的應用程序和遊戲都包含了DirectX運行期部分。 它目前有五個版本:一、二、三、5和6(沒有版本4)。不一樣版本具備不一樣的運行期部分,但新版本的運行期部分可與舊版本的應用程序配合,即向上兼容。當前大部分流行的遊戲都是基於版本5開發的。 第二節 DirectX5 SDK的得到 DirectX SDK包括開發DirectX應用程序所須要到的所有示例和幫助文件,但這些都是可 選資源,必須的文件是頭文件(.h文件)和庫文件(.lib文件)。得到DirectX SDK比得到運行期部分要困難一些。Windows NT 4.0和Win95都不帶DirectX SDK,要得到SDK可經過如下3種辦法: * 購買Visual c++5.0(包括DirectX SDK) * 訪問Microsoft Web站點的DirectX下載頁 * 成爲MSDN(Microsoft開發網絡)用戶 SDK 也能夠從Microsoft Web站點上得到,下載量很大,尤爲是在撥號鏈接時,有可能須要一整夜的時間。 成爲MSDN用戶是獲取SDK的好辦法,除非您反對經過Microsoft付費的方式得到升級及其操做系統的程序開發特權。SDK由MSDN level 2及以上提供。 第三節 元件對象模型(COM) DirectX根據Microsoft的COM(Component Object Model,即元件對象模型)規格得以實現。COM設計成用來提供徹底便攜的、安全的、可升級的軟件結構。COM使用一個面向對象的模型,這要比像C++等語言所用的模型更嚴格。例如,COM對象常常經過成員函數進行存取,並且並不具有公共數據成員。COM對繼承性的支持與C++相比也是有限的。 不少DirectX中API是做爲COM對象的實例來建立的。您能夠這樣看:對象就象一個黑盒子,它表明了硬件,從而須要經過一個接口與應用程序進行聯絡。經過COM接口發送和接收的命令被稱爲「方式(method)」。例如,方式IDirectDraw2::GetDisplayMode是經過接口IDirectDraw2發送,從而可以從DirectDraw對象獲得當前顯示適配器的顯示模式。 COM對象提供實際函數性,而COM接口則提供存取函數性的方法。COM對象不能被直接存取,相反,全部的存取者經過接口來完成。這條規則是如此強有力的獲得遵照,以至於咱們不能給任何COM對象以名稱。咱們只能給用來存取對象的接口名稱。 全部的COM接口都是從IUnknown接口中衍生出來的。「I」標誌常常用於命名COM接口(它表明Interface即接口)。 IUnknown接口提供3個成員函數,全部COM接口於是繼承這些函數: ●AddRef():使對象內部引用值加一。例如,當您建立一個新的接口時,構造函數將自動調用AddRef()。 ●QueryInterface():讓COM對象就它們是否支持特定接口進行查詢。例如,升級的COM對象提供附加的接口,而非現有接口的修改版。QueryInterface()函數能夠用來肯定舊的接口,以決定新的接口是否被支持。若是被查詢的對象不支持有問題的接口,則更替接口的指針就返回。 ●Release():使對象內部引用值減一。您應該在接口的指針將要超出範圍時或者要經過使用接口指針來結束時使用這個函數。 對象的每個DirectX接口都表明了一種設備,例如IDirectDraw二、IDirectSound和IDirectPlay。DirectX對象模型象徵性地爲每個設備提供了一個主對象,其它所支持的功能對象由主對象衍生而來。例如,DirectDraw對象表明了顯示適配器,您能夠由它建立DirectDrawSurface對象來表明顯存。一樣地,DirectSound對象表明聲卡並能夠建立DirectSoundBuffer對象表明聲卡上的聲音資料。 在C程序中能夠調用任意的COM接口方式。下面的例子建立一個平面,使用DirectDraw對象的IDirectDraw2::CreateSurface方式: ret = lpDD->lpVtbl->CreateSurface (lpDD, &ddsd, &lpDDS,        NULL);  這裏lpDD表示與新建平面相關的DirectDraw對象。該方式填充一個平面類型的結構(&ddsd)並返回一個指向平面的指針(&lpDDS)。 一樣功能用C++的實現爲: ret = lpDD->CreateSurface(&ddsd, &lpDDS, NULL)  第四節 DirectDraw DirectDraw是DirectX SDK中的一個組件,它容許用戶直接地操做顯存,支持硬件覆蓋、內存與顯存反轉。DirectDraw在提供這些功能的同時並支持基於Microsoft Windows的應用程序和設備驅動。DirectDraw做爲一種軟件接口,支持Windows的GDI(圖像設備接口),並提供直接操做顯示設備的功能。它提供了與設備無關的遊戲、Windows子系統等軟件開發方式。 它還可以支持許多種顯示硬件,包括從簡單的SVGA顯示器到高級硬件性能(支持圖像剪切、延伸和非RGB顏色格式)。接口的設計使您的應用程序可以知道所使用硬件的特性,從而能夠支持它們的硬件加速功能。 關於DirectDraw,在之後還將有更加詳細的講解。 第五節 DirectSound Microsoft DirectSound的API是DirectX平臺軟件開發工具(SDK)程序員指南的聲音組件。DirectSound提供了硬件加速、對聲音設備的直接操做。在提供這些功能的同時,它還保持了與當前設備驅動的兼容性。 新版本的DirectSound可以在運行中查詢硬件性能以肯定最優的操做方式,還具備抓獲聲音、低延遲混音等功能特性。它的新功能還包括支持屬性集(Porperty Sets),從而即便DirectSound不直接支持新硬件的特性,它也可以利用並受益。 DirectSound是經過「硬件抽象層(HAL)」來操做聲音硬件的,這是一個由聲音設備驅動來實現的接口。HAL提供瞭如下功能: 要求和釋放對聲音硬件的控制; 描述聲音硬件的特性; 在硬件容許的條件下實現特定的操做; 在硬件不容許的時候報告操做失敗。 DirectSound可以自動地利用硬件加速,包括硬件混音和硬件聲音緩衝。您的應用程序無須查詢硬件和程序特性,而能夠在運行期部分查詢DirectSound來得到對聲音設備特性的充分描述,而後根據各個特性的存在或缺乏來使用不一樣的方法進行優化。您還能夠指定接受硬件加速的聲音緩衝區。 下圖顯示了DirectSound與系統中其它聲音組件的關係:   關於DirectSound,在之後還將有更加詳細的講解。 第六節 DirectPlay DirectPlay的主要做用在於使應用程序間通信方式得以簡單化。DirectPlay的技術不只提供了一個方案,實現了通信與傳送協議及在線服務的無關性,並且還實現了與傳輸服務器和遊戲服務器的無關性。萬一所基於的網絡不支持某一方式,DirectPlay包含了必要的代碼來仿效它。 DirectPlay的service provider結構使應用程序與網絡隔絕開來。應用程序經過查詢DirectPlay來得到所基於網絡功能特性(例如延遲、帶寬等),從而相應地調整通信方式。下面的圖顯示了DirectPlay service provider的結構:    使用DirectPlay的第一步是選擇使用哪種service provider,它決定了將用於通信的網絡或協議。協議能夠是遍及Internet的TCP/IP、局域網中的IPX或兩臺計算機間的鏈接電纜。 DirectPlay提供了兩種頗有用的鏈接管理方式: IDirectPlay3::EnumConnections列舉了應用程序能夠得到的全部鏈接; IDirectPlay3::InitializeConnection初始化一種特定的鏈接。 在肯定了網絡的鏈接後,爲了方便理解下面的內容,先來看看這樣幾個概念: 首先從session講起。DirectPlay session是若干臺計算機之間的通信通道。一個應用程序只有在成爲了某個session的一部分後纔可以開始與其它計算機進行通信。有兩種方法能夠實現:列舉一個網絡中全部存在的session而後加入其中的一個;或新建一個session並等待其它計算機的加入。當應用程序成爲session的一部分後,它就能夠建立一個player並與session中其它的player相互傳遞信息。 每個session中都有一臺計算機做爲主機。主機是session的全部者並擁有惟一的改動session屬性的權力。 下圖顯示了一個session模型:   Session有兩種類型:對等類型和客戶/服務器類型。 Player是session中邏輯概念上的對象,可以發送和接收消息。在DirectPlay Session中沒有對實體計算機的表示方法。Player能夠做爲一個本地player(在您本身的計算機上),或做爲一個遠程player(在其它計算機上)。只有在擁有了至少一個player後,計算機纔可以發送和接收消息。每一臺計算機能夠擁有不止一個本地player。 Group是在邏輯概念上是一些player的集合。經過建立一個group,一個應用程序能夠向它發送消息使其中全部的player都收到。DirectPlay提供了管理group和成員關係的方式。 下圖顯示了一個session內容的邏輯結構:   假如,一臺計算機在完成了鏈接以後,就能夠調用IDirectPlay3::EnumSessions列舉全部能夠獲得的session。而後,IDirectPlay3::Open根據session cache中的內容加入一個session,或新建一個session。 接下來,能夠建立player和group。而在遊戲中,更多的是經過Message Managment中的各個方式進行頻繁地、大量的消息傳送。 在不一樣類型的session中,消息的流向是不一樣的。在對等類型中,消息的傳送是各個player之間直接進行的。對於使用multicast向group中傳送消息時,則要在group中指定一個multicast server,經過它再將消息傳送給group中其它的計算機。 在客戶/服務器類型的session中,全部的player只與服務器進行直接通信,再由它與其它各個客戶機進行消息傳送。下圖表示了這樣的關係:   第七節 DirectInput DirectInput用以支持包括鼠標、鍵盤和遊戲杆等在內的輸入設備,甚至還有力度反饋的高級輸入/輸出設備。它也是基於COM的。 DirectInput對象由輸入設備提供數據。每個相應設備都有所謂「對象實例」,即個別的控件,如按鍵、按紐和遊戲杆的軸向等。鍵盤上的每個按鍵均可以做爲鍵盤對象的一個對象實例。即便程序在後臺運行,DirectInput也可以對輸入設備作出響應。 通常來講,先要建立一個DirectInput對象(經過DirectInputCreat方式),表示一個DirectInput子系統。而後,列舉出系統中能夠獲得的輸入設備,再爲這些個別設備建立DirectInputDevice對象(經過IDirectInput::CreateDevice方式)。這種對象的方式用於獲取關於設備的信息,設置它們的屬性並從它們那裏獲得數據。 下面給出一個使用鼠標的例子。您能夠在光盤Example目錄下的Scrawl.c文件中找到這些代碼。 首先建立DirectInput鼠標設備 // LPDIRECTINPUT    g_pdi;    // 已被初始化 LPDIRECTINPUTDEVICE g_pMouse;  HRESULT             hr;  hr = g_pdi->CreateDevice(GUID_SysMouse, &g_pMouse, NULL); if (FAILED(hr)) {     Complain(hwnd, hr, "CreateDevice(SysMouse)");     return FALSE; } CreateDevice方式有三個參數:第一個是全局獨有標誌符GUID_SysMouse,這裏代表爲鼠標;第二個是IDirectInputDevice接口指針類型,若是這個調用成功,它就指向可用的鼠標;通常不使用COM聚合體,第三個參數爲NULL。 而後,設置鼠標信息的格式: hr = g_pMouse->SetDataFormat(&c_dfDIMouse); if (FAILED(hr)) {     Complain(hwnd, hr, "SetDataFormat(SysMouse, dfDIMouse)");     return FALSE; } 設置鼠標行爲: hr = g_pMouse->SetCooperativeLevel(hwnd,                DISCL_EXCLUSIVE | DISCL_FOREGROUND); //後面的兩個標誌符實現了前臺運行時對輸入設備的獨佔  if (FAILED(hr)) {     Complain(hwnd, hr, "SetCooperativeLevel(SysMouse)");     return FALSE; } 要使用事件通告(event notification)來發覺鼠標的動做並將通過緩衝的鼠標輸入讀進來,這都須要進行一些設置。首先,建立一個事件,將它與鼠標聯繫起來。當發生硬件中斷時,就能夠告訴鼠標設備對象有新的數據來到。 // HANDLE  g_hevtMouse;   // 全局變量 g_hevtMouse = CreateEvent(0, 0, 0, 0); if (g_hevtMouse == NULL) {     Complain(hwnd, GetLastError(), "CreateEvent");     return FALSE; }   hr = g_pMouse->SetEventNotification(g_hevtMouse);   if (FAILED(hr)) {     Complain(hwnd, hr, "SetEventNotification(SysMouse)");     return FALSE; }   如今您須要設定緩衝區大小。在此以前要初始化一個DIPROPDWORD結構,這當中不少數量是可有可無的,關鍵是最後一個,dwData,它決定了緩衝區中可容納項目的數量。 #define DINPUT_BUFFERSIZE  16 DIPROPDWORD dipdw =     {         // the header         {             sizeof(DIPROPDWORD),        // diph.dwSize             sizeof(DIPROPHEADER),       // diph.dwHeaderSize             0,                          // diph.dwObj             DIPH_DEVICE,                // diph.dwHow         },         // the data         DINPUT_BUFFERSIZE,              // dwData     };   接着按照您但願改變的屬性的標誌符,將頭地址傳送給IDirectInputDevice::SetProperty方式: hr = g_pMouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);   if (FAILED(hr)) {     Complain(hwnd, hr, "Set buffer size(SysMouse)");     return FALSE;  }   至此,設置結束。而後開始根據程序的要求操做鼠標。 第八節 Direct3D Direct3D提供了與硬件無關的的3D視頻硬件操做方式。您能夠在兩種模式(當即模式和保留模式)中選擇其中之一使用。 當即模式較保留模式是一個低層的3D API,後者建構於前者之上。當即模式適合於開發高品質的多媒體應用程序,它在底層與加速硬件進行通信。保留模式應用於對3D場景進行實時的操縱。 對3D場景的操做是基於矩陣和多邊形的運算,這是建立和管理3D的基礎知識,在不少資料中都可得到。 使用當即模式能夠選擇經過調用DrawPrimitive方式或利用執行緩衝區。對於初學者通常從調用DrawPrimitive方式。不過,千萬不要認爲二者有優劣之分。在熟悉了Direct3D後,使用哪一個方法取決於您應用程序的要求。前者的方法與其它COM雷同;在利用執行緩衝區的方法時,要建立DirectDraw和Direct3D對象,設置渲染狀態,填充執行緩衝區等。 不管哪一種模式,應用程序與硬件的通信都很相似。正以下圖所示。因爲Direct3D至關於DirectDraw對象的一個接口,這裏的HAL被表示爲DirectDraw/Direct3D HAL。   對保留模式的操做是經過使用一些對象來實現的。Direct3D和DirectDraw是緊密聯繫在一塊兒的。一個DirectDraw對象將DirectDraw和Direct3D狀態封裝起來,經過IDirectDraw::QueryInterface方式將IDirect3D接口轉換爲DirectDraw對象。 有一個很重要的概念是z緩衝區。它決定了將不少顯示內容如何覆蓋和裁剪。若是沒有z緩衝區,保留模式沒法給覆蓋層排序。沒有指定z順序的覆蓋層被缺省設定爲0,處於最底層。一共能夠有四十億個覆蓋層(應該夠用了吧!),z順序爲2的層將可能遮掩了z順序爲1的層的某些內容。記住,不能有兩個層的z順序相同。 關於3D場景,還有諸如材資、光源等概念,在此再也不一一聱述。 第九節   Vc++中引入Direct SDK 一旦安裝了SDK,就得立刻通知Visual C++ SDK的位置。默認狀態下,SDK安裝在dxsdk目錄下。頭文件放在dxsdk/inc目錄下,庫文件放在dxsdk/lib目錄下。 可利用下述兩種方法之一通知visual C++ SDK的位置。一種方法是在使用文件時給出完整的文件路徑;另外一種法是將這些目錄加到Visual  C++的搜索路徑中。第二種方法更好一些,能夠經過Tools[Options]Directories對話框實現。 增長dxsdk/lib目錄的方法大致上同增長dxsdk/inc目錄的方法相同。 若是你得到了一個含有比Visual C++的DirectX SDK新的版本,您須要將DirectX SDK目錄置於常規的Visual C++目錄上面。不然就得使用舊版本。(Visual C++從上至下查找目錄) 根據咱們已經討論過的內容,你應該可以編輯DirectX程序了。然而還有最後一個潛在的障礙。除非INITGUID符號已經被定義,不然在DirectX GUIDs下調用Query-Interface()函數的程序同DirectX2 SDK的連接會失敗。INITGUID符號只能由一個源文件定義,而且必須出如今#include語句以前,以下列代碼所示: #define INITGUID #include〈ddraw.h〉 //…other includes…    對於DirectX3及以上版本,這種解決方法都是有效的,但還有一個更好的方法,即將dxguid.lib文件連接到你的工程上(Build[Settings]Link對話框),以替代INITGUID符號的定義。 此最後兩個參數的內容依賴於消息的類型。     產生消息   消息傳送概念使Windows可以實現多任務。消息有四個基原本源。應用程序能夠從用戶那兒接受消息,也能夠是Windows自己,應用程序自己或者是其它應用程序。   用戶消息包括按鍵消息、鼠標移動、鼠標指點或單擊、菜單選擇、滾動條的定位等。應用程序必須花費大量的時間來處理用戶消息。用戶產生的消息代表運行程序的人但願改變應用程序的表現方式。   不管什麼時候,若是狀態發生改變,將會有一個消息被髮往應用程序。一個例子是用戶單擊了應用程序的圖標,代表他們想要將此應用程序變爲活動的應用程序。在這種狀況下,Windows告訴應用程序它的主窗口被打開了,它的大小和位置被改變了等等Windows產生的消息能夠被處理,也能夠被忽略,這跟應用程序當前的狀態有關。     相應消息     在傳統的面向過程的C語言Windows應用程序中,對於遇到的每一種消息,它都有一個相應的過程來處理這消息。不一樣的窗口對相同的消息會產生不一樣的響應。Windows把每一個消息發送到應用程序的不一樣窗口,而不一樣的窗口對相同的消息會有不一樣解釋。不令應用程序須要不一樣的過程來處理每一種消息,每個窗口也應有不一樣的過程來處理不一樣的消息。窗口過程集合了應用程序的全部消息處理過程。     消息循環     全部Windows應用程序的一個基本組成就是消息處理循環。每個C應用程序都在內部執行這個操做。C應用程序包含了建立並初始化窗口的過程,隨後是消息處理循環,最後是結束應用程序所需的一些代碼。消息循環負責處理Windows發給主程序的消息。在這兒,程序知道有了消息,而且要求Windows將消息發送到合適的窗口過程以供處理。當消息被接受時,窗口過程就執行但願的動做。             第八節 windows的函數     Windows嚮應用程序開發人員提供了數以百計的函數。這些函數的例子包括DispatchMes-sage(),PostMessage(),RegisterWindowMessage()以及SetActiveWindow()。對於使用基礎類庫的C++程序員,許多函數自動被運行。     在16位的Windows 3.x下的函數聲明包括一個pascal修飾符,這在DOS下更爲有效Windows95和Windows NT下的32位應用程序再也不使用這個修飾符。如你所知,全部Windows函數的參數是經過系統來傳遞的。函數的參數從最右邊的參數開始向左壓入棧,這是標準的C方式。在從函數返回以前,調用過程必須按原來壓入棧的字節數調整棧指針。       第九節 windows應用程序框架     Windows頭文件:WINDOWS.H     WINDOWS.H頭文件(以及其它相關文件)是全部程序的內在部分。傳統上,WINDOWS.H是全部C語言編寫的Windows應用程序必需的一部分。當在C++中使用基礎類庫時,WINDOWS.H包括在AFXWIN.H頭文件中。      Windows應用程序的組成    在開發Windows應用程序的過程當中有一些重要的步驟:   *用C語言編寫WinMain()函數和相關的窗口函數,或者在C++中使用基礎類,好比CWinApp等。     *建立菜單、對話框和其它資源並把它們放入資源描述文件。     *(可選)使用Vinsual C++編譯器中的企業編輯器來建立對話框。     *(可選)使用Vinsual C++編譯器中的企業編輯器來建立對話框。     *用項目文件來編譯並連接全部的C/C++源程序和資源文件       Windows應用程序中的組成部分            1. WinMain()函數     Windows 95和Windows NT須要一個WinMain()函數。這是應用程序開始執行和結束的地方。     從Windows向WinMain()傳遞四個參數。下面的代碼段演示了這些參數的使用:      int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPreInst,           LPSTR 1pszCmdLine, int nCmdShow)     第一個參數hInst包含了應用程序的實例句柄。當應用程序在Windows下運行時,這個數字惟一標識了應用程序。     第二個參數hPreInst將始終是一個NULL值,代表沒有這個應用程序的其它實例正在運行,由於在Windows 95和Windows NT下每一個應用程序都在它本身單獨的地址空間中運行。     第三個參數1pszCmdLine是指向一個以'/0'結尾的字符串的長指針,這個字符串表明了應用程序的命令行參數。     WinMain()的第四個參數是nCmdShow。在nCmdShow中存儲的整數表明了Windows預約義的許多常量中的一個,它決定了窗口顯示的方式。     2. WNDCLASS     WinMain()負責註冊應用程序的主窗口類。每一個窗口類都創建在一些用戶選擇的風格、字體、標題字、圖標、大小、位置等的基礎上。窗口類其實是定義這些屬性的一個模板。   基本上,全部的Windows類定義都使用相同的標準C/C++結構。下面的例子是一個說明WNDCLASSW結構的typedef語句,WNDCLASS是從這兒繼承的:      typedef struct tagWNDCLASSW           UINT      style;           WNDPROC   1pfnWndProc;           int       cbClsExtra;           int       cbWndExtra;           HANDLE    hInstance;           HICON     hIcon;           HCURSOR   hCursor;           HBR8USH   hbrBackground;           LPCWSTR   1pszMenuName;           LPCWSTR   1pszClassName;           WNDCLASSW,*PWNDCLASSW,NEAR*NPWNDCLASSW,            FAR*LPWNDCLASSW;     下面的部分討論了WNDCLASS結構中的不一樣的域。其中有些域能夠被賦予NULL,告訴Windows使用缺省的預約義值。     style:style域指明瞭類風格。   1pfnWndProc:接受一個指向窗口函數的指針,它將執行全部的窗口任務。   cbClsExtra:指定了必須在窗口類結構後面分配的字節數,它能夠是NULL。   cbWndExtra:指定了必須在窗口實例後面分配的字節數,它能夠是NULL。   hInstance:定義了註冊窗口類的應用程序實例。它必須是一個實例句柄,不得是NULL。   hIconhIcon:劃定利用窗口最小化時顯示的圖標。它能夠是NULL。   hCursorhCursor:定義了應用程序使用的光標。這個句柄能夠是NULL。     hbrBackground:提供了背景刷子的標識符。     1pszMenuName:是指向一個以空字符結尾的字符串的指針。這個字符串是菜單的資源名。這一項能夠爲NULL。     1pszClassName:是指向一個以空字符結尾的字符串的指針。這個字符串是窗口類的名字。             3.WNDCLASSEX     Windows提供了一種擴展的WNDCLASS定義,名爲WNDCLASSEX,它容許應用程序使用小圖標。下面是WNDCLASSEX結構的定義:      typedef struct WNDCLASSEX           UINT      style;           WNDPROC   1pfnWndProc;           int       cbClsExtra;           int       cbWndExtra;           HANDLE    hInstance;           HICON     hIcon;           HCURSOR   hbrBackground;           LPCTSTR   1pszMenuName;           LPCTSTR   1pszClassName;           HICON     hIconSm;        WNDCLASSEX;     你能夠看到這兩個結構是相同的,除了WNDCLASSEX包括了hIconSm成員,這是與窗口類有關的小圖標的句柄。     4.定義窗口類     應用程序能夠定義它們本身的窗口類,只要先定義一個合適類型的結構,而後用窗口類的信息來填充結構的域。     下面的代碼示範瞭如何定義並初始化一個WNDCLASS結構。      char szProgName[]="ProgName";           .           .           .      WNDCLASS wcApp;           .           .           .      wcApp.1pszClassName=szProgName;      wcApp.hInstance=hInst;      wcApp.1pfnWndProc=WndProc;      wcApp.hCursor=LoadCursor(NULL,IDC-ARROW);      wcApp.hIcon=NULL;      wcApp.1pszMenuName=szAppIName;      wcApp.hbrBackground=GetStockObject(WHITE-BRUSH);      wcApp.style=CS-HREDRAW| CS-VREDRAW;      wcApp.cbClsExtra=0;      wcApp.cbWndExtra=0;      if(!RegisterClass (&wcApp))           return 0;     WNDCLASS結構中的第二個域是wcApp.hInstance,它被賦予了WinMain()被激活後返回的hInst的值。這指明瞭應用程序的當前實例。1pfnWndProc被賦予執行全部窗口任務的窗口函數的指針地址。對於大部分應用程序,這個函數叫作WndProc()。   注意:WndProc()是一個用戶定義而不是預約義的函數名。在賦值語句以前必須給出函數原型。        wcApp.hCursor域被賦予實例的光標句柄。     當wcApp.1pszMenuName被賦予NULL值的時候,Windows就認爲這個窗口類沒有菜單。  若是有,菜單必須有一個名字,它必須出如今引號裏面。GetStockOject()函數返回一個刷子句柄,用於在這個類建立的窗口用戶區中畫出背景色。     wcApp.style窗口類風格被設爲CS-HREDRAW或CS-VREDRAW。     最後的兩個域,weApp.cbClsExtra以及wcApp.cbWndExtra常常被設爲0。這些域能夠被選用以指明窗口結構和窗口數據結構後面應該保留的附加字節數。    下面這段代碼用於註冊窗口類:      if(!hpreInst)                 .           .           .      if(! RegisterClass(&wcApp))           return FALSE;           Windows 95和Windows NT經過檢查hPreInst的值來肯定多少個實例,而hPreInst老是NULL,因此就註冊窗口類.     5.建立窗口     窗口經過調用CreateWindow()函數來建立。這個過程對全部版本的Windows都是同樣的。窗口類定義了窗口的通常特徵,容許同一個窗口類被用於多個不一樣的窗口,CreateWin-dow()函數的參數指明瞭關於窗口的更詳細的信息。  CreateWindow()函數的參數信息包括如下內容:窗口類、窗口標題、窗口風格、幕位置、窗口的父句柄、菜單句柄、實例句柄以及32位的附加信息。在大部分應用程序中 ,這個函數會是下面這個樣子:      hWnd=CreateWindow(szProgName,"Simple Windows Program",           WS-OVERLAPPEDWINDOW,CW-USEDEFAULT,           CW-USEDEFAULT,CW-USEDEFAULT,           CW-USEDEFAULT,(HWND)NULL,(HMENU)NULL,           (HANDLE)hInst,(LPSTR)NULL);     第一個域szProgName(已賦過值)定義了窗口的類,後面是窗口標題條上使用的標題。窗口的風格是第三個參數     下面的六個參數表明了窗口的x、y座標和x、y方向的大小,而後是父窗口句柄和窗口菜單句柄。每一個域都被賦予一個缺省值。hInst域包含了程序的實例句柄,後面是一個附加參數(NULL)。     顯示和更新窗口   在Windows下,ShowWindow()函數被用來實際顯示一個窗口。下面的代碼示範了這個函數:      Show Window(hWnd,nCmdShow);     在調用CreateWindow()時生成的窗口句柄被用做hWnd參數。ShowWindow()的第二個參數是nCmdShow,決定了窗口被如何顯示。這個顯示狀態也被稱爲窗口的可視狀態。     顯示窗口的最後一步是調用Windows的Update Window()函數。      UpdateWindow(hWnd);        6.消息循環      一旦調用Win-Main()函數並顯示了窗口,應用程序就須要一個消息處理循環。最經常使用的實現方法是使用一個標準的while循環:      while (GetMessage (&lpMsg,NULL,0,0))      {           TranslateMessage(&lpMsg);           DispatchMessage(&lpMsg);      }        GETMESSAGE()函數:應用程序要處理的下一個消息能夠經過調用Windows的GetMessage()函數來取得。        NULL參數指示函數取回這個應用程序的任何窗口的任何消息。最後兩個參數0和0告訴GetMessage()不要使用任何消息過濾器。消息過濾器可以將接收到的消息限制在一個明確的範圍以內,如鍵盤消息或鼠標消息等。     通常應用程序應該確認通向消息循環的全部步驟都已經正確地執行過了。這包括確認每一個窗口類都已經註冊過,都已經被建立。不然,一旦進入了消息循環,只有一個消息可以結束這個循環。不管什麼時候處理了WM-QUIT消息,返回值是FALSE。這會引起主循環關閉例程。WM-QUIT消息是應用程序退出消息循環的惟一途徑。     TRANSLATEMESSAGE()函數:經過TranslateMessage()函數,虛擬消息能夠被轉換爲字符消息。     DISPATCHMESSAGE()函數:Windows經過DispatchMessage()函數將當前的消息發送到正確的窗口過程。 *******    窗口函數        全部的應用程序都必須包括一個WinMain()函數和一個回調窗口函數。由於一Win-dows應用程序從不直接訪問任何窗口函數,每一個應用程序都必須向Windows提出請求以執行規定的操做。        一個回調函數在Windows中註冊,當Windows要對一個窗口進行操做時,它就被調用。各個應用程序的回調函數的實際代碼長度會大不相同。窗口函數自己能夠很是小,只處理一個或兩個消息,也能夠很是大並且複雜。     下面的代碼段(不完整的應用程序說明語句)顯示了在應用程序中的回調窗口函數WndProc()的一個範例:      LRESULT CALLBACK WndProc(HWND hWnd,UNIT messg,                WPARAM wParam,LPARAM 1Param)                 HDC hdc;           PAINTSTRUCT ps;           switch(messg)                           case WM-PAINT:                     hdc=BeginPaint(hWnd,&ps);                          .                          .                          .                     ValidateRect(hWnd,NULL);                     EndPaint(hWnd,&ps);                     break;                case WM-DESTROY:                postQuitMessage(0);                break;           default:                return(DefWindowProc(hWnd,messg,wParam,1param));                      return(0);           Windows但願窗口類結構定義中wcApp,1pfnWndProc域的名字可以與回調函數的名 字匹配。後面用這個窗口類建立的全部窗口的回調函數都應該用WndProc()的名字。     下面的代碼段討論一個窗口類結構中回調函數名的位置和賦值:                .                .                .           wcApp.1pszClassName=szProgName;           wcApp.hInstance=hInst;           wcApp.1pfnWndProc=WndProc;                .                .                .         Windows有向百個消息能夠發送給窗口函數。這些消息用「WM-」打頭的標識符來 標識。        WndProc()的第一個參數是hWnd。hWnd包含了Windows發送消息的窗口句柄。         函數的第二個參數messg按WINUSER.H中的定義指明瞭即將被處理的實際消息。最後的兩個參數wParam以及1Param,指明瞭處理每一個消息所需的附加信息。     WndProc()函數繼續定義了兩個變量:hdc指明瞭顯示設備句柄,ps指明瞭存儲用戶區 信息所需的一個PAINTSTRUCT結構。     回調函數被用於檢查將被處理的消息並選擇執行適當的動做。這個選擇過程一般在一個標準的C語言的switch語句中完成。 模塊定義文件     正如你在前面學到的,LINK提供了全部Windows應用程序須要的模塊定義文件在命令行方式下的替代品。模塊定義文件向連接器提供有關的定義和描述信息,這樣連接器就能夠知道如何來組織Windows應用程序的可執行文件。這些信息已經成爲新執行文件格式的文件頭的一部分。     注意:在Windows 95和Windows NT下面,你不太可能須要建立一個模塊定義文件。這些信息是爲了完整性和向後兼容。        第十節 VC++提供的windows編程工具   Visual C++編譯器包含幾個資源編輯器。單獨的編輯器能夠經過編譯器主菜單中的Insert Resource菜單來運行。圖形對象都是資源,象圖標、光標、消息框、對話框、字體、位圖、畫筆、刷子等。資源表明應用程序的可執行文件中包含的數據。   資源編譯器RC.EXE是一個Windows資源的編譯器。。   資源以及附加的編譯器的使用增長了應用程序開發的複雜性。可是它容易在項目工具中使用。     項目文件   項目文件提供了概覽資源和程序代碼編譯過程的手段,同時也可使應用程序的可執行版本保持最新。它們跟蹤源文件的日期和時間以實現這些加強的功能。項目文件包含了有關特定程序的編譯鏈過程的信息。項目文件是在集成的C或C++編輯環境中建立的。項目文件還支持加強的編譯和連接。     資源   當你使用VisualC++編譯器提供的資源編輯器時,用本身的圖標、指針和位圖來定製Windows應用程序很是容易。這些編輯器給你提供了一個開發圖形資源的完整環境。這些編輯器同時也能幫助你開發菜單和對話框-Windows下數據輸入的基本手段。這些編輯器還能幫你操縱單獨的位圖、加速鍵和字符串。。     資源編輯器   每一種編輯器都在VisualC++環境中提供,都是編譯器的一個集成的部分。這樣,每種編輯器都是在Windows下運行的徹底集成的資源開發工具。你能夠經過選擇Insert Resource來啓動每一種編輯器。     下面咱們將經過教程演示資源編輯器的使用。請單擊返回,而後運行教程。 ?  第十一節 MFC的基本概念   基礎類庫爲你提供了易於使用的對象。將Windows與C++聯繫起來是很天然的,這樣就能夠充分利用面向對象技術的優勢。MFC開發組實現了大量的Windows應用程序編程接口(API)。這個C++庫在一些可重用的類中封裝了最重要的數據結構和API函數調用。   相似MFC這樣的類庫比起前面兩章討論的C程序員使用的函數庫有不少優勢。     下面列出了C++類的一些優勢,好比:   *用類對數據和代碼進行封裝   *繼承性   *消除函數和變量名的衝突   *類是語言的天然擴展   *一般,精心設計的庫減小了代碼量   利用基礎類庫,建立一個窗口所需的代碼大約只佔傳統應用程序的三分之一。這就可使程序員只用花不多的時間與Windows打交道,把更多的精力集中在開發本身的程序代碼上。 22.2 MFC的設計考慮   基礎類庫設計小組定義了嚴格的設計規則,在設計MFC庫時必須遵循這些規則。這些規則和方針以下:   *利用C++的威力,但不能把程序員嚇倒   *使從標準API調用到類庫的轉換儘量簡單   *容許混合使用傳統的函數調用和新的類庫   *在設計類庫的時候綜合考慮功能和效率   *建成的類庫必須可以方便地在不一樣平臺間移植,如Windows 95和Windows NT     設計小組感到要開發高質量的代碼必須從MFC庫自己開始。C++基礎類庫必須又小又快。它的簡單性使它易於使用,而執行速度與龐大的C函數庫接近。   這些類的設計方式應該讓熟練的Windows程序員沒必要從新學習各類函數的名字。經過仔細的命名和設計能夠實現這一點。Microsoft認爲這一點是MFC區別於其它類庫的一個特徵。     MFC小組還把基礎類庫設計爲是容許以混合方式編程的。這就是說,在同一個源文件裏,既可使用類也可使用傳統的函數調用。即便是在使用MFC時,相似SetCursor()和GetSystemMetrics()這樣的函數仍是須要直接調用。     Microsoft也知道類庫必須方便使用。其它廠商提供的一些類庫設計得太抽象。按Microsoft的說法,這些笨重的類企圖生成又大又慢的應用程序。MFC庫提供了合理的抽象,保證代碼很小。     開發小組將原始的MFC庫設計爲動態的而不是靜態的。動態的結構是這些類能夠適應咱們如今使用的Windows 95和Windows NT環境。 22.3 MFC庫的關鍵特性     從其它編譯器廠商那兒也能夠得到Windows類庫,但Microsoft宣稱他們的MFC類庫具備許多真正的優勢:   *全面支持全部的Windows函數、控件、消息、GDI(圖形設備接口)繪圖原語、菜單以及對話框。   *使用與Windows API相同的命名約定。所以,從名字上就能夠直接知道類的功能。   *消除了一個錯誤源,即大量的switch/case語句。全部的消息都被映射到類的成員函數。這種消息-方法的映射方法應用於全部的消息。   *可以把對象的信息輸出到文件,這提供了更好的診斷支持。同時還提供了驗證成員變量的能力。   *加強的例外處理設計,使得程序代碼失敗的可能性更小。可以解決「內存不足」以及其它一些問題。   *能夠在運行時決定數據對象的類型。這容許對類的域進行動態操縱。   *小而快速的代碼。前面已經提到,MFC庫只添加了不多一些代碼,執行起來幾乎與傳統的C語言Windows應用程序同樣快。     *對組件對象模型(COM)的支持。     有經驗的Windows程序員會馬上喜歡上其中的兩個特性:熟悉的命名約定和消息-方法映射機制。若是你從新檢查一下在第二十一章中開發的應用程序的源代碼,你會看到大量用於處理錯誤的switch/case語句。還應該注意這些應用程序調用了大量的API函數。當你使用MFC庫的時候,這兩種現象都消失或減小了。     專業程序員確定會欣賞在MFC庫中實現的更好的診斷和很小的代碼。如今程序員就能夠利用MFC庫的好處而沒必要擔憂他們的應用程序的代碼大小了。     最後,MFC是惟一真正有用的類庫。 22.4 一切從CObject類開始     相似MFC這樣的類庫一般都來自不多的幾個基類。而後,另外的類就能夠從這些基類中繼承而來。CObject是在開發Windows應用程序時大量使用的一個基類。在MFC/INCLUDE子目錄下提供的MFC庫頭文件包括了許多類定義信息。     咱們來簡單地看一下,CObject,它在頭文件AFX。H中有定義:      ///////////////      //class CObject is the root of all compliant objects      class CObject            public:      //Object model(types,destruction,allocation)           virtual CRuntimeClass*GetRuntimeClass () const;           virtual~CObject();//virtual destructors are necessary      //Diagnostic allocations      void*PASCAL operator new(size-t nSize);      void*pascal operator new(size-t,void*p);      void PASCAL operator delete(void*p);      #if defined(-DEBUG)&&!defined(-AFX-NO-DEBUG-CRT)      //for file name/line number tracking using DEBUG-NEW      void* PASCAL operator new(size-t nSize,                LPCSTR 1pszFileName,                int nLine);      //Disable the copy constructor and assignment by default      //so you will get compiler errors instead of unexpected      //behavior if you pass objects by value or assign objects.      protected:           CObject();      private:           CObject(const CObject& objectSrc);//no implementation           void operator=(const CObject& objectSrc);      //Attributes      public:           BOOL IsSerializable()const;           BOOL IsKindOf(const CRuntimeClass*pClass)const;      //Overridables           virtual void Serialize (CArchive& ar);           //Diagnostic Support           virtual void AssertValid()const;           virtual void Dump(CDumpContext& dc)const;      //Implementation      public:           static const AFX-DATA CRuntimeClass classCObject;      #ifdef-AFXDLL           static CRuntimeClass*PASCAL-GetBaseClass();      #endif      ;     爲了清楚起見,對這段代碼做了一些細微的改動。但和你在頭文件AFX.H能夠找到的代碼基本同樣。     檢查CObject的代碼,注意構成這個類定義的成分。首先,CObject被分爲公有、保護和私有三個部分。CObject還提供了通常的和動態的類型檢查以及串行化的功能。回憶一下,動態類型檢查使你能夠在運行時肯定對象的類型。藉助於永久性的概念,對象的狀態能夠被保存到存儲介質中,好比磁盤。對象的永久性使對象成員函數也能夠是永久的,容許對象數據的恢復。     子類從基類繼承而來。例如,CGdiObject是一個從CObject類繼承來的類。這兒是AFXWIN。H中找到的CGdiObject類定義。一樣,爲了清楚起見,對其做了一些改動。      //////////////////////      //CGdiObjet abstract class for CDC SelectObject      class CGdiObject:public CObject            DECLARE-DYNCREATE(CGdiObject)      public:      //Attributes           HGDIOBJ m-hObject;//must be first data member           operator HGDIOBJ()const;           static CGdiObject*PASCAL FromHandle(HGDIOBJ hObject);           static void PASCAL Delete TempMap();           BOOL Attach (HGDIOBJ hObject);           HGDIOBJ Detach();      //Constructors           CGdiobject();//must create a derived class object           BOOL DeleteObject();      //Operations           int GetObject (int nCount,LPVOID 1pObject)const;           UINT GetObjectType()const;           BOOL CreateStockObject(int nIndex);           BOOL UnrealizeObject();           BOOL operator==(const CGdiObject& obj)const;           BOOL operator!=(const CGdiObject& obj)const;      //Implementation      public:           virtual~CGdiObject();      #ifdef-DEBUG           virtual void Dump(CDumpContext& dc)const;           virtual void AssertValid()const;      #endif      ;     CGdiObject和它的成員函數容許在Windows應用程序中建立並使用繪畫對象,如自定義畫筆、刷子和字體等。諸如CPen之類的類是進一步從CGdiObject類繼承而來的。     Microsoft提供了MFC庫的所有源代碼,以儘量地增長編程的靈活性。可是,對於初學者,沒有必要去了解不一樣的類是如何定義的。     例如,在傳統的C語言Windows應用程序中,DeleteObject()函數按下面的語法調用:      DeleteObject(hBRUSH);/*hBRUSH is the brush handle*/     在C++中,利用MFC庫,能夠按下面的語法訪問類成員函數以實現一樣的目的:      newbrush.DeleteObject();//new brush is current brush     正如你能夠看到的,從C語言Windows函數調用轉向類庫對象是簡單的。Microsoft在開發全部Windows類的時候都使用這種方法,使得從傳統函數調用到繼承類庫對象的轉移很是簡單。  第二章 windows編程基礎   第一節 引言  爲了跟上潮流,咱們拋棄了已快被淘汰的DOS操做系統,全部的講解和例程都是基於微軟的Windows操做系統的。考慮到不少的用戶並無Windows編程基礎,因此咱們設置了這一專門講述、討論Windows的術語、概念的部分,以使這部分用戶能較快地理解和掌握咱們所講述、討論的編程思想和編程方法。這一部分中主要講述的是Windows中十分基本的東西,因此用戶應根據本身的狀況有選擇的進行學習。好!如今就讓咱們進入艱苦而又精彩有趣的遊戲編程之路吧!    第二節 windows的介紹        Windows應用程序能夠採用面向過程的實現方法。也可使用面向對象的結構。全部的實現方法都集成了點擊控制和彈出菜單,可以運行特別爲Windows編寫的應用程序。        Windows是一種基於圖形界面的多任務操做系統。爲這個環境開發的程序(那些專門爲Windows設計的)有着相同的外觀和命令結構。對用戶來講,這使得學習使用Windows應用程序變得容易了。爲了幫助開發Windows應用程序,Windows提供了大量的內建函數以方便地使用彈出菜單、滾動條、對話框、圖標和其餘一些友好的用戶界面應該具備的特性。   Windows運行應用程序以硬件無關的方式來處理視頻顯示、鍵盤、鼠標、打印機、串行口以及系統時鐘。        最值得注意的Windows特性就是其標準化的圖形用戶界面。統一的界面使用圖片或圖標來表明磁盤驅動器、文件、子目錄以及其它操做系統的命令和動做。 統一的用戶界面也爲程序員帶來了好處。例如,你能夠很方便地使用常見菜單和對話框的內建函數。全部的菜單都具備相同風格的鍵盤和鼠標接口,由於是Windows而不是程序員在實現它。        Windows的多任務環境容許用戶在同一時刻運行多個應用程序或同一個應用程序的多個實例。一個應用程序可能處於激活狀態。激活的應用程序是指它正接收用戶的輸入。由於每個瞬間僅有一個程序可以被處理,所以同一時間也只能有一個應用程序處於激活狀態。可是,能夠有任意個數的並行運行的任務。      第三節 windows的基本概念   Windows消息和麪向對象編程   Windows實現了一種仿OOP(面向對象編程)環境。Windows下的消息系統負責在多任務環境中分解信息。從應用程序的角度來看,消息是關於發生的事件的通知。用戶能夠經過按下或移動鼠標來產生這些事件,也能夠是經過改變窗口大小或選擇一個菜單項等。這些事件也能夠由應用程序自己產生。Windows自己也能產生消息。如「關閉Windows」消息,Windows經過這個消息來通知全部的應用程序,Windows將被關閉。   內存管理   在Windows系統中系統內存是最重要的共享資源之一。當同一時刻有多個應用程序在運行時,爲了避免耗盡系統資源,每一個應用程序必須合做以共享內存。同時,當啓動新的程序和關閉老的程序時,內存會變得碎片化。經過移動內存中的代碼和數據塊,Windows可以使內存空閒空間連起來。在Windows下也有可能超量使用內存。例如,應用程序能夠比內存容量大。Windows可以廢棄當前不使用的代碼,在之後須要時再從應用程序中將之讀入內存。Windows應用程序能夠共享可執行文件中的例程。包含可共享的例程的文件稱爲動態連接庫(DLL)。Windows包括了運行時將DLL例程鏈入程序的機制。     硬件無關性   Windows同時提供了硬件或設備無關性,使你免於在生成程序的時候不得不考慮全部可能使用的顯示器、打印機或輸入設備。在Windows下面,每種硬件設備的驅動程序只編寫一次。硬件無關性使編程對應用程序開發者來講更爲簡單。應用程序與Windows而不是各類設備打交道。     動態鍵接庫   動態鍵接庫提供了更多的Windows功能。它們經過一個有力而靈活的圖形用戶界面加強了基本的操做系統。動態鍵接庫包括一些預約義的函數,它們能夠在一個應用程序被調入時與之鍵接(動態地),而不是在應用程序被建立時(靜態地)。動態鍵接庫使用DLL後綴。函數庫將每個程序員從重複開發諸如讀取字符或格式化輸出之類的通用例程中解放出來。程序員能夠方便地構造它們本身的庫以包含更多的功能,好比改變字體或檢驗文本。把函數變爲通用工具減小了冗餘設計,這是OOP的一個關鍵特性。        Windows的庫是被動態地鍵接的。或者說,鍵接器並不把函數拷貝到程序的可執行文件中去。相反,當程序運行時,它產生對庫函數的調用。天然,這樣作節約了內存。無論有多少應用程序在運行,在RAM中老是隻有庫的一份考貝,而這個庫能夠被共享。        Windows的可執行文件格式         Windows具備一種新的可執行文件的格式,稱爲New Excutable格式。它包括新型的文件頭,可以保存有關DLL函數的信息。           第四節 windows的窗口   Windows的窗口   窗口看起來就是顯示設備中的一個矩形區域,它的外觀與特定的應用程序無關,但是,對於一個應用程序來講,窗口是屏幕上應用程序可以直接控制的矩形區域。應用程序可以建立並控制主窗口的一切,如大小和形狀。當用戶啓動一個程序時,一個窗口就被建立了。用戶每次單擊窗口,應用程序做出響應。關閉一個窗口會使應用程序結束。多窗口帶給用戶Windows的多任務能力。經過將屏幕分爲不一樣的窗口,用戶可以使用鍵盤或鼠標選擇一個並行運行的應用程序,以此對多任務環境中的一個特定程序進行輸入,Windows截取了用戶的輸入並分配必要的資源(例如微處理器)。 Windows的佈局   全部的Windows應用程序都具備諸如邊框、控制菜單、About對話框之類的共同特徵。這些特徵使得各個Windows應用程序很是相似。 邊框     Windows的窗口被邊框所包圍。邊框由圍出窗口的線條組成。對於新手而言,邊框看起來僅僅是爲了將一個應用程序的屏幕視口與其它的區別開。可是,對於熟練者,邊框有着不一樣的做用。例如,若是將鼠標指針放在邊框上並按下鼠標的左鍵,用戶就能夠改變窗口的大小。 標題條     應用程序的名字顯示在窗口頂部的標題條中。標題條老是在相關窗口頂部的中央。標題條很是有用,它能夠幫助你記住正在運行哪一個應用程序。活動應用的標題條以不一樣於非活動應用程序的顏色顯示。 控制圖標     控制圖標是每一個窗口左上方的小圖片,每一個應用程序都使用它。在控制圖標上單擊鼠標鍵會使Windows顯示系統菜單。 系統菜單     當用鼠標單擊控制圖標時就打開了控制菜單。它提供了諸如Restore,Move,Size,Minimize,Maximize以及Close這樣的標準操做。 最小化圖標     每一個Windows 95或Windows NT應用程序都在窗口的右上角顯示三個圖標。最左邊的圖標是一段短下劃線,這就是最小化圖標。它可使用程序被最小化。 最大化圖標     最大化圖標是三個圖標中中間的那一個,看起來象兩個小窗口。使用最大化圖標可使用應用程序佔滿整個屏幕。若是選擇了這個圖標,其它應用程序窗口都會被蓋住。 垂直滾動條     若是有必要,應用程序能夠顯示一個垂直滾動條。垂直流動條顯示在應用程序窗口的右邊,在兩端有兩個方向相反的箭頭。它還有一個着色的棒和一個透明的窗口塊。後者被用於顯示當前顯示內容與整個文檔(着色的棒)的關係。你能夠用滾動條來選擇顯示哪一頁。通常在任何一個箭頭上單擊一下會使顯示內容移動一行。單擊向上箭頭下方的窗口塊並拖動它會使屏幕輸出快速更新到應用程序屏幕輸出的任意位置。 水平滾動條     也能夠顯示一個水平滾動條。水平滾動條顯示在窗口的底部,具備與垂直滾動條相似的功能。你用它來選擇要顯示哪些列。通常在任何一個箭頭上單擊一個會使顯示內容移動一列。單擊向左箭頭右邊的窗口塊並拖動它會使屏幕輸出快速更新到應用程序屏幕輸出的任意位置。 菜單條     一個可選擇的菜單條能夠顯示在標題條的下方。經過菜單條來選擇菜單和子菜單。這種選擇能夠經過用鼠標單擊,也能夠用熱鍵組合來實現。熱鍵組合常常是ALT與命令中帶下劃線的字母的組合,好比File命令中的「F」。 用戶區     一般用戶區佔據了窗口最大的部分。這是應用程序的基本輸出區域。應當由應用程序來複雜管理用戶區。另外,應用程序能夠輸出到用戶區。   第五節 windows的類       窗口的基本組件有助於說明應用程序的外觀。有的時候應用程序須要建立兩個外觀和表現都類似的窗口。Windows的Paint就是一個例子。藉助於同時運行Paint的兩個實例(或拷貝),Paint容許用戶剪貼或拷貝圖片的一部分。而後信息就能夠從一個實例拷貝到另外一個實例。Paint的每一個運行實例的外觀和表現都與其餘的相同。這就須要每一個實例建立本身的外觀和功能相似的窗口。     在這種狀況下被建立的外觀和功能都很相似的窗口被稱爲是屬於同一個窗口類的。可是,你建立的窗口能夠有不一樣的特徵。它們能夠有不一樣的大小,不一樣的位置,不一樣的顏色或不一樣的標題,也可使用不一樣的光標。     每一個被建立的窗都基於一個窗口類。在用C語言開發撕於的基於傳統的函數調用方式的應用程序中,一些窗口爲在Windows應用程序初始化的進修註冊。你的應用程序能夠註冊屬於本身的窗口類。爲了可以使幾個窗口在同一個窗口類的基礎上建立,Windows定義了一些窗口特徵,如CreateWindows()的參數,另外一些定義的窗口類的結構。當你註冊一個窗口類的時候,這個類能夠被Windows下運行着的任何程序所使用。對於使用MFC的應用程序來講,多數註冊工做已經由預約義的對象完成了。     具備類似的外觀和表現的窗口能夠被組合成一個類,以此來減小須要維護的信息。由於每一個窗口類都有本身的可共享的類結構,不須要複製沒必要要的窗口類參數。同時,同類的兩個窗口使用相同的函數以及相關的例程。這樣能夠節省時間和空間,由於不存在代碼複製。   第六節 windows中的面向對象編程       在Windows下傳統的C程序吸取了一些面向對象編程的特性。對象是一種包含數據結構和對這些數據結構進行操做的函數的抽象數據類型。並且,對象接收會引發它們不一樣動做的消息。     好比,一個Windows的圖形對象是能夠被做爲一個實體來操縱的一些數據的集合,對於用戶它是可視界面的一部分。特別地,一個對象意味這數據和數據的功能。菜單、標題條、控制塊以及滾動條等都是圖形對象的例子。下一部分描述一些影響應用程序外觀的新的圖形對象。     圖標   圖標是用來使用記住特定操做、想法或產品的小圖形對象。好比,一個電子表格程序被最小化時能夠顯示一個很小的柱狀圖以提醒用戶這個程序還在運行之中。在柱狀圖上雙擊鼠標會使Windows激活這個應用程序。圖標是很是有力的工具。它很適合用來引發用戶的注意,好比在發出錯誤警告或者是向用戶提供選擇時。     光標   光標是Windows用來跟蹤指點設備的運動的圖形符號。這種圖形符號能夠改變形狀以指明特定的Windows操做。好比,當標準的箭頭光標變爲沙漏光標時說明Windows正在執行一個命令,須要暫停。     編輯光標   應用程序在窗口中顯示編輯光標以告訴用戶在哪兒輸入。編輯光標與其餘屏幕符號顯然不一樣,由於它是閃爍的。多數時候,鼠標輸入與光標相連,而鍵盤輸入與編輯光標相連。可是,能夠用鼠標來改變編輯光標的輸入點。     消息框   消息框是另外一類Windows圖形對象。消息框是一種包含標題、圖標和消息的彈出式窗口。圖(?)是關閉Windows Notepad程序時出現的一個標準的消息框。   ------------------------------------------------------------------------- |                                                                          |       ------------------------------------------------------------------------       Windows的對話框   對話框與消息框類似的地方在於它也是一種彈出式窗口。可是對話框主要用於接受用戶輸入而不只僅是顯示一些輸出。對話框容許應用程序接受輸入,每次一個域或是一個框的內容,而不是每次一個字符。圖(?)顯示了一個典型的Windows對話框。對知框的圖形設計由Windows爲你自動完成。對話框的佈局一般用編譯器中的資源編輯器完成。     -----------------------------------------------------------------------               |                                                                       |     -----------------------------------------------------------------------           字體   字體是一種圖形對象或資源,它定義了完整的字符集合的字樣。這些字符都有一個特定的大小和風格,可使文本具備不一樣的外觀。字樣是字符的一種基本屬性,它定義了字符的襯線和筆畫寬度。     位圖        位圖是一種顯示圖片(按像素組織),存儲於內存。當應用程序須要快速顯示圖片時可使用位圖。由於位圖直接從內存中傳送,因此它比用程序從新畫出圖片要快得多。位圖有兩個基本用途。首先,它能夠在屏幕上顯示圖片。其次位圖也用於建立刷子。刷子使你能夠在屏幕上畫出並填充對象。   使用位圖有兩個缺點。首先,與其尺寸有關,位圖會佔據難以預估的大量內存。每一個被顯示的像素都要在內存中佔據相應的空間。在彩色顯示器上顯示一個像素會比在單色顯示器上佔據更多的內存。在單色顯示器上,只需一位(bit)就能夠表示出像素的狀態。但是在能夠顯示16種顏色的彩色顯示器上,須要四位才能表示一個像素的特徵。一樣地,隨着顯示設備分辨率的增長,位圖對內存的需求也增長了。位圖的另外一個缺點是它只包括靜態的圖片。好比,若是用位圖來表明一輛汽車,就沒有辦法來訪問圖片的不一樣部分,如輪踏、頂蓋、窗等。可是,若是汽車是有一系列基本繪圖例程來生成的,應用程序就能夠改變向這些例程傳送的數據從而改變圖片的不一樣部分。例如,應用程序能夠修飾頂蓬線並把一輛轎車變爲敞蓬車。     畫筆   當Windows在屏幕上顯示一個圖形時,它使用當前畫筆的信息。畫筆用於畫出線條或輪廊。畫筆具備三個基本特徵:線寬、線型(虛線、短線、實線)以及顏色。Windows永遠保留着用於畫白線和黑線的畫筆,任何應用程序可使用它。你也能夠建立本身的畫筆。    刷子   Windows用刷子來畫出顏色並以預約義的樣式來填充一個區域。刷子至少有8×8個像素大小。刷子有三個基本特徵:樣式和顏色。因爲它們至少有8×8的大小,刷子被稱做具備樣式而不象畫筆,稱爲線型。樣式能夠是純的顏色,也能夠是陰影線、斜線或其它用戶自定義的組合    第七節 windows的消息    Windows的消息   在Windows中,應用程序並不直接寫屏幕、處理硬件中斷或直接對打印機輸出。相反,應用程序使用合適的Windows函數或者等待一個適當的消息被髮出。   Windows消息系統負責在多任務環境中分派消息。從應用程序的角度來看,消息能夠看做是發生的事件的通知,有些須要做出特定的反應,有些就不須要。這些事件可能由用戶產生,好比按下了鼠標或移動了鼠標,改變了窗口的大小或者選擇了一個菜單。同時,這些事件也可能由應用程序自己所產生。   這個過程使你的應用程序必須徹底面向消息處理。當接收到消息時,應用程序必須能激活並決定正確的動做,完成這個動做以後回到等待狀態。   經過檢查消息的格式和來源,下一部分將更仔細地討論消息系統。 消息的格式   消息通知一個應用程序發生了一個事件。從技術上來說,消息不只僅是與應用程序相關,並且是與應用程序的某一特定窗口有關。所以,全部的消息都被髮往窗口。   在Windows下只有一個消息系統-即系統消息隊列。可是,每一個正在Windows下運行的應用程序都有它本身的消息隊列。系統消息隊列中的每一個消息最終都要被USER模塊傳送到應用程序的消息隊列中去。應用程序的消息隊列中存儲了程序的全部窗口的所有消息。   無論消息具備什麼類型,它們都有四個參數:一個窗口句柄,一個消息類型,兩個附加的32位參數。窗口消息中定義的第一個參數是消息所關聯的窗口句柄。   在編寫Windows應用程序的時候常用句柄。句柄是一個惟一的數字,它被用於標識許多類型的對象,如菜單、圖標、畫筆和刷子、內存分配、輸出設備甚至窗口實例。在Windows 95和Windows NT下面,程序的每一個運行着的拷貝叫作實例。   由於Windows 95和Windows NT容許你同時運行一個程序的多個實例,操做系統就有必要保持對這些實例的追蹤。這是經過賦予每一個運行實例一個惟一的實例句柄來實現的。   實例句柄一般被用做一個內部維護着的表的索引。經過引用表中的元素而不是實際的內存地址,Windows 95和Windows NT能夠動態地調整全部的資源,而只需在此資源所對應的表格位置中插入一個新的地址。   根據一個應用程序的多個實例被處理的方式,內存資源由Windows 95和Windows NT保存。   應用程序的實例具備很重要的做用。應用程序的實例定義了程序的函數所需的全部對象。這包括控件、菜單、對話框以及更多的新Windows類。   消息中的第二個參數是消息類型。這是在Windows獨有的一些頭文件中定義的標識符。這些頭文件能夠經過WINDOWS.H來使用。在Windows下,每一個消息由兩個字符的助記符開始,跟着是下劃線,最後是一個描述符。   最後的兩個參數提供瞭解釋消息所需的附加信息。所以最後兩個參數的內容依賴於消息的類型。     產生消息   消息傳送概念使Windows可以實現多任務。消息有四個基原本源。應用程序能夠從用戶那兒接受消息,也能夠是Windows自己,應用程序自己或者是其它應用程序。   用戶消息包括按鍵消息、鼠標移動、鼠標指點或單擊、菜單選擇、滾動條的定位等。應用程序必須花費大量的時間來處理用戶消息。用戶產生的消息代表運行程序的人但願改變應用程序的表現方式。   不管什麼時候,若是狀態發生改變,將會有一個消息被髮往應用程序。一個例子是用戶單擊了應用程序的圖標,代表他們想要將此應用程序變爲活動的應用程序。在這種狀況下,Windows告訴應用程序它的主窗口被打開了,它的大小和位置被改變了等等Windows產生的消息能夠被處理,也能夠被忽略,這跟應用程序當前的狀態有關。        相應消息        在傳統的面向過程的C語言Windows應用程序中,對於遇到的每一種消息,它都有一個相應的過程來處理這消息。不一樣的窗口對相同的消息會產生不一樣的響應。Windows把每一個消息發送到應用程序的不一樣窗口,而不一樣的窗口對相同的消息會有不一樣解釋。不令應用程序須要不一樣的過程來處理每一種消息,每個窗口也應有不一樣的過程來處理不一樣的消息。窗口過程集合了應用程序的全部消息處理過程。        消息循環        全部Windows應用程序的一個基本組成就是消息處理循環。每個C應用程序都在內部執行這個操做。C應用程序包含了建立並初始化窗口的過程,隨後是消息處理循環,最後是結束應用程序所需的一些代碼。消息循環負責處理Windows發給主程序的消息。在這兒,程序知道有了消息,而且要求Windows將消息發送到合適的窗口過程以供處理。當消息被接受時,窗口過程就執行但願的動做。           第八節 windows的函數   Windows嚮應用程序開發人員提供了數以百計的函數。這些函數的例子包括DispatchMes-sage(),PostMessage(),RegisterWindowMessage()以及SetActiveWindow()。對於使用基礎類庫的C++程序員,許多函數自動被運行。     在16位的Windows 3.x下的函數聲明包括一個pascal修飾符,這在DOS下更爲有效Windows95和Windows NT下的32位應用程序再也不使用這個修飾符。如你所知,全部Windows函數的參數是經過系統來傳遞的。函數的參數從最右邊的參數開始向左壓入棧,這是標準的C方式。在從函數返回以前,調用過程必須按原來壓入棧的字節數調整棧指針。     第九節 windows應用程序框架   Windows頭文件:WINDOWS.H        WINWS.H頭文件(以及其它相關文件)是全部程序的內在部分。傳統上,WINDOWS.H是全部C語言編寫的Windows應用程序必需的一部分。當在C++中使用基礎類庫時,WINDOWS.H包括在AFXWIN.H頭文件中。         Windows應用程序的組成   在開發Windows應用程序的過程當中有一些重要的步驟:   *用C語言編寫WinMain()函數和相關的窗口函數,或者在C++中使用基礎類,好比CWinApp等。       *建立菜單、對話框和其它資源並把它們放入資源描述文件。       *(可選)使用Vinsual C++編譯器中的企業編輯器來建立對話框。       *(可選)使用Vinsual C++編譯器中的企業編輯器來建立對話框。       *用項目文件來編譯並連接全部的C/C++源程序和資源文件     Windows應用程序中的組成部分              1. WinMain()函數        Windows 95和Windows NT須要一個WinMain()函數。這是應用程序開始執行和結束的地方。       從Windows向WinMain()傳遞四個參數。下面的代碼段演示了這些參數的使用:      int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPreInst,           LPSTR 1pszCmdLine, int nCmdShow)       第一個參數hInst包含了應用程序的實例句柄。當應用程序在Windows下運行時,這個數字惟一標識了應用程序。       第二個參數hPreInst將始終是一個NULL值,代表沒有這個應用程序的其它實例正在運行,由於在Windows 95和Windows NT下每一個應用程序都在它本身單獨的地址空間中運行。        第三個參數1pszCmdLine是指向一個以'/0'結尾的字符串的長指針,這個字符串表明了應用程序的命令行參數。        WinMain()的第四個參數是nCmdShow。在nCmdShow中存儲的整數表明了Windows預約義的許多常量中的一個,它決定了窗口顯示的方式。        2. WNDCLASS        WinMain()負責註冊應用程序的主窗口類。每一個窗口類都創建在一些用戶選擇的風格、字體、標題字、圖標、大小、位置等的基礎上。窗口類其實是定義這些屬性的一個模板。   基本上,全部的Windows類定義都使用相同的標準C/C++結構。下面的例子是一個說明WNDCLASSW結構的typedef語句,WNDCLASS是從這兒繼承的:      typedef struct tagWNDCLASSW           UINT      style;           WNDPROC   1pfnWndProc;           int       cbClsExtra;           int       cbWndExtra;           HANDLE    hInstance;           HICON     hIcon;           HCURSOR   hCursor;           HBR8USH   hbrBackground;           LPCWSTR   1pszMenuName;           LPCWSTR   1pszClassName;           WNDCLASSW,*PWNDCLASSW,NEAR*NPWNDCLASSW,            FAR*LPWNDCLASSW;     下面的部分討論了WNDCLASS結構中的不一樣的域。其中有些域能夠被賦予NULL,告訴Windows使用缺省的預約義值。     style:style域指明瞭類風格。   1pfnWndProc:接受一個指向窗口函數的指針,它將執行全部的窗口任務。   cbClsExtra:指定了必須在窗口類結構後面分配的字節數,它能夠是NULL。   cbWndExtra:指定了必須在窗口實例後面分配的字節數,它能夠是NULL。   hInstance:定義了註冊窗口類的應用程序實例。它必須是一個實例句柄,不得是NULL。   hIconhIcon:劃定利用窗口最小化時顯示的圖標。它能夠是NULL。   hCursorhCursor:定義了應用程序使用的光標。這個句柄能夠是NULL。        hbrBackground:提供了背景刷子的標識符。        1pszMenuName:是指向一個以空字符結尾的字符串的指針。這個字符串是菜單的資源名。這一項能夠爲NULL。        1pszClassName:是指向一個以空字符結尾的字符串的指針。這個字符串是窗口類的名字。                3.WNDCLASSEX        Windows提供了一種擴展的WNDCLASS定義,名爲WNDCLASSEX,它容許應用程序使用小圖標。下面是WNDCLASSEX結構的定義:       typedef struct WNDCLASSEX           UINT      style;           WNDPROC   1pfnWndProc;           int       cbClsExtra;           int       cbWndExtra;           HANDLE    hInstance;           HICON     hIcon;           HCURSOR   hbrBackground;           LPCTSTR   1pszMenuName;           LPCTSTR   1pszClassName;           HICON     hIconSm;        WNDCLASSEX;       你能夠看到這兩個結構是相同的,除了WNDCLASSEX包括了hIconSm成員,這是與窗口類有關的小圖標的句柄。    4.定義窗口類      應用程序能夠定義它們本身的窗口類,只要先定義一個合適類型的結構,而後用窗口類的信息來填充結構的域。     下面的代碼示範瞭如何定義並初始化一個WNDCLASS結構。      char szProgName[]="ProgName";           .           .           .      WNDCLASS wcApp;           .           .           .      wcApp.1pszClassName=szProgName;      wcApp.hInstance=hInst;      wcApp.1pfnWndProc=WndProc;      wcApp.hCursor=LoadCursor(NULL,IDC-ARROW);      wcApp.hIcon=NULL;      wcApp.1pszMenuName=szAppIName;      wcApp.hbrBackground=GetStockObject(WHITE-BRUSH);      wcApp.style=CS-HREDRAW| CS-VREDRAW;      wcApp.cbClsExtra=0;      wcApp.cbWndExtra=0;      if(!RegisterClass (&wcApp))           return 0;        WNDCLASS結構中的第二個域是wcApp.hInstance,它被賦予了WinMain()被激活後返回的hInst的值。這指明瞭應用程序的當前實例。1pfnWndProc被賦予執行全部窗口任務的窗口函數的指針地址。對於大部分應用程序,這個函數叫作WndProc()。   注意:WndProc()是一個用戶定義而不是預約義的函數名。在賦值語句以前必須給出函數原型。        wcApp.hCursor域被賦予實例的光標句柄。        當wcApp.1pszMenuName被賦予NULL值的時候,Windows就認爲這個窗口類沒有菜單。若是有,菜單必須有一個名字,它必須出如今引號裏面。GetStockOject()函數返回一個刷子句柄,用於在這個類建立的窗口用戶區中畫出背景色。     wcApp.style窗口類風格被設爲CS-HREDRAW或CS-VREDRAW。     最後的兩個域,weApp.cbClsExtra以及wcApp.cbWndExtra常常被設爲0。這些域能夠被選用以指明窗口結構和窗口數據結構後面應該保留的附加字節數。    下面這段代碼用於註冊窗口類:      if(!hpreInst)                 .           .           .      if(! RegisterClass(&wcApp))           return FALSE;           Windows 95和Windows NT經過檢查hPreInst的值來肯定多少個實例,而hPreInst老是NULL,因此就註冊窗口類.        5.建立窗口        窗口經過調用CreateWindow()函數來建立。這個過程對全部版本的Windows都是同樣的。窗口類定義了窗口的通常特徵,容許同一個窗口類被用於多個不一樣的窗口,CreateWin-dow()函數的參數指明瞭關於窗口的更詳細的信息。     CreateWindow()函數的參數信息包括如下內容:窗口類、窗口標題、窗口風格、屏幕位置、窗口的父句柄、菜單句柄、實例句柄以及32位的附加信息。在大部分應用程序中 ,這個函數會是下面這個樣子:      hWnd=CreateWindow(szProgName,"Simple Windows Program",           WS-OVERLAPPEDWINDOW,CW-USEDEFAULT,           CW-USEDEFAULT,CW-USEDEFAULT,           CW-USEDEFAULT,(HWND)NULL,(HMENU)NULL,           (HANDLE)hInst,(LPSTR)NULL);     第一個域szProgName(已賦過值)定義了窗口的類,後面是窗口標題條上使用的標題。窗口的風格是第三個參數     下面的六個參數表明了窗口的x、y座標和x、y方向的大小,而後是父窗口句柄和窗口菜單句柄。每一個域都被賦予一個缺省值。hInst域包含了程序的實例句柄,後面是一個附加參數(NULL)。     顯示和更新窗口   在Windows下,ShowWindow()函數被用來實際顯示一個窗口。下面的代碼示範了這個函數:      Show Window(hWnd,nCmdShow);     在調用CreateWindow()時生成的窗口句柄被用做hWnd參數。ShowWindow()的第二個參數是nCmdShow,決定了窗口被如何顯示。這個顯示狀態也被稱爲窗口的可視狀態。     顯示窗口的最後一步是調用Windows的Update Window()函數。      UpdateWindow(hWnd);        6.消息循環      一旦調用Win-Main()函數並顯示了窗口,應用程序就須要一個消息處理循環。最經常使用的實現方法是使用一個標準的while循環:      while (GetMessage (&lpMsg,NULL,0,0))      {           TranslateMessage(&lpMsg);           DispatchMessage(&lpMsg);      }        GETMESSAGE()函數:應用程序要處理的下一個消息能夠經過調用Windows的GetMessage()函數來取得。        NULL參數指示函數取回這個應用程序的任何窗口的任何消息。最後兩個參數0和0告訴GetMessage()不要使用任何消息過濾器。消息過濾器可以將接收到的消息限制在一個明確的範圍以內,如鍵盤消息或鼠標消息等。     通常應用程序應該確認通向消息循環的全部步驟都已經正確地執行過了。這包括確認每一個窗口類都已經註冊過,都已經被建立。不然,一旦進入了消息循環,只有一個消息可以結束這個循環。不管什麼時候處理了WM-QUIT消息,返回值是FALSE。這會引起主循環關閉例程。WM-QUIT消息是應用程序退出消息循環的惟一途徑。     TRANSLATEMESSAGE()函數:經過TranslateMessage()函數,虛擬消息能夠被轉換爲字符消息。     DISPATCHMESSAGE()函數:Windows經過DispatchMessage()函數將當前的消息發送到正確的窗口過程。 *******    窗口函數        全部的應用程序都必須包括一個WinMain()函數和一個回調窗口函數。由於一Win-dows應用程序從不直接訪問任何窗口函數,每一個應用程序都必須向Windows提出請求以執行規定的操做。        一個回調函數在Windows中註冊,當Windows要對一個窗口進行操做時,它就被調用。各個應用程序的回調函數的實際代碼長度會大不相同。窗口函數自己能夠很是小,只處理一個或兩個消息,也能夠很是大並且複雜。     下面的代碼段(不完整的應用程序說明語句)顯示了在應用程序中的回調窗口函數WndProc()的一個範例:      LRESULT CALLBACK WndProc(HWND hWnd,UNIT messg,                WPARAM wParam,LPARAM 1Param)                 HDC hdc;           PAINTSTRUCT ps;           switch(messg)                           case WM-PAINT:                     hdc=BeginPaint(hWnd,&ps);                          .                          .                          .                     ValidateRect(hWnd,NULL);                     EndPaint(hWnd,&ps);                     break;                case WM-DESTROY:                postQuitMessage(0);                break;           default:                return(DefWindowProc(hWnd,messg,wParam,1param));                      return(0);           Windows但願窗口類結構定義中wcApp,1pfnWndProc域的名字可以與回調函數的名 字匹配。後面用這個窗口類建立的全部窗口的回調函數都應該用WndProc()的名字。     下面的代碼段討論一個窗口類結構中回調函數名的位置和賦值:                .                .                .           wcApp.1pszClassName=szProgName;           wcApp.hInstance=hInst;           wcApp.1pfnWndProc=WndProc;                .                .                .         Windows有向百個消息能夠發送給窗口函數。這些消息用「WM-」打頭的標識符來 標識。        WndProc()的第一個參數是hWnd。hWnd包含了Windows發送消息的窗口句柄。         函數的第二個參數messg按WINUSER.H中的定義指明瞭即將被處理的實際消息。最後的兩個參數wParam以及1Param,指明瞭處理每一個消息所需的附加信息。     WndProc()函數繼續定義了兩個變量:hdc指明瞭顯示設備句柄,ps指明瞭存儲用戶區 信息所需的一個PAINTSTRUCT結構。     回調函數被用於檢查將被處理的消息並選擇執行適當的動做。這個選擇過程一般在一個標準的C語言的    }  鄾{                     F:\遊戲資料集合\遊戲核心編程\Chapter3.txt                                                                                                                                                                                                                           F:\遊戲資料集合\遊戲核心編程\.Chapter3.txt.map                                                                                                                                                                                                                      F:\遊戲資料集合\遊戲核心編程\.Chapter3.txt.blk                                                                                                                                                                                                                      鄍m     ㄡg         T!  ?  ㄡg         h    ㄡg            ㄡg            `  ㄡg         悪                       ?H                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          v  ?p      }  ` 第三章 DirectX  SDK簡介 第一節 關於DirectX SDK Microsoft DirectX提供了一套很是優秀的應用程序接口,包含了設計高性能、實時應用程序的源代碼。DirectX技術將幫助您建構下一代的電腦遊戲和多媒體應用程序。它的內容包括了DirectDraw、DirectSound、DirectPlay、Direct3D和DirectInput等部分,它們分別主要應用在圖形程序、聲音程序等方面。 因爲DirectX,使在Windows下運行應用程序的性能能夠與在DOS或遊戲平臺下運行的應用程序性能相媲美,甚至超過它們。它將爲您的Windows遊戲開發提供一個具備魯棒性的、標準化的操做環境。 DirectX包括兩部分:運行期部分(Runtime)和SDK。在DirectX開發時,這兩部分都要用到,但在DirectX應用程序運行時只用運行期部分。在Windows NT 4.0及以上版本中含有DirectX運行期部分,Win95則沒有。但Win95能夠很容易得到DirectX運行期部分。而Windows NT 4.0之前的版本不能運行DirectX程序。許多基於DirectX的應用程序和遊戲都包含了DirectX運行期部分。 它目前有五個版本:一、二、三、5和6(沒有版本4)。不一樣版本具備不一樣的運行期部分,但新版本的運行期部分可與舊版本的應用程序配合,即向上兼容。當前大部分流行的遊戲都是基於版本5開發的。 第二節 DirectX5 SDK的得到 DirectX SDK包括開發DirectX應用程序所須要到的所有示例和幫助文件,但這些都是可 選資源,必須的文件是頭文件(.h文件)和庫文件(.lib文件)。得到DirectX SDK比得到運行期部分要困難一些。Windows NT 4.0和Win95都不帶DirectX SDK,要得到SDK可經過如下3種辦法: * 購買Visual c++5.0(包括DirectX SDK) * 訪問Microsoft Web站點的DirectX下載頁 * 成爲MSDN(Microsoft開發網絡)用戶 SDK 也能夠從Microsoft Web站點上得到,下載量很大,尤爲是在撥號鏈接時,有可能須要一整夜的時間。 成爲MSDN用戶是獲取SDK的好辦法,除非您反對經過Microsoft付費的方式得到升級及其操做系統的程序開發特權。SDK由MSDN level 2及以上提供。 第三節 元件對象模型(COM) DirectX根據Microsoft的COM(Component Object Model,即元件對象模型)規格得以實現。COM設計成用來提供徹底便攜的、安全的、可升級的軟件結構。COM使用一個面向對象的模型,這要比像C++等語言所用的模型更嚴格。例如,COM對象常常經過成員函數進行存取,並且並不具有公共數據成員。COM對繼承性的支持與C++相比也是有限的。 不少DirectX中API是做爲COM對象的實例來建立的。您能夠這樣看:對象就象一個黑盒子,它表明了硬件,從而須要經過一個接口與應用程序進行聯絡。經過COM接口發送和接收的命令被稱爲「方式(method)」。例如,方式IDirectDraw2::GetDisplayMode是經過接口IDirectDraw2發送,從而可以從DirectDraw對象獲得當前顯示適配器的顯示模式。 COM對象提供實際函數性,而COM接口則提供存取函數性的方法。COM對象不能被直接存取,相反,全部的存取者經過接口來完成。這條規則是如此強有力的獲得遵照,以至於咱們不能給任何COM對象以名稱。咱們只能給用來存取對象的接口名稱。 全部的COM接口都是從IUnknown接口中衍生出來的。「I」標誌常常用於命名COM接口(它表明Interface即接口)。 IUnknown接口提供3個成員函數,全部COM接口於是繼承這些函數: ●AddRef():使對象內部引用值加一。例如,當您建立一個新的接口時,構造函數將自動調用AddRef()。 ●QueryInterface():讓COM對象就它們是否支持特定接口進行查詢。例如,升級的COM對象提供附加的接口,而非現有接口的修改版。QueryInterface()函數能夠用來肯定舊的接口,以決定新的接口是否被支持。若是被查詢的對象不支持有問題的接口,則更替接口的指針就返回。 ●Release():使對象內部引用值減一。您應該在接口的指針將要超出範圍時或者要經過使用接口指針來結束時使用這個函數。 對象的每個DirectX接口都表明了一種設備,例如IDirectDraw二、IDirectSound和IDirectPlay。DirectX對象模型象徵性地爲每個設備提供了一個主對象,其它所支持的功能對象由主對象衍生而來。例如,DirectDraw對象表明了顯示適配器,您能夠由它建立DirectDrawSurface對象來表明顯存。一樣地,DirectSound對象表明聲卡並能夠建立DirectSoundBuffer對象表明聲卡上的聲音資料。 在C程序中能夠調用任意的COM接口方式。下面的例子建立一個平面,使用DirectDraw對象的IDirectDraw2::CreateSurface方式: ret = lpDD->lpVtbl->CreateSurface (lpDD, &ddsd, &lpDDS,        NULL);  這裏lpDD表示與新建平面相關的DirectDraw對象。該方式填充一個平面類型的結構(&ddsd)並返回一個指向平面的指針(&lpDDS)。 一樣功能用C++的實現爲: ret = lpDD->CreateSurface(&ddsd, &lpDDS, NULL)  第四節 DirectDraw DirectDraw是DirectX SDK中的一個組件,它容許用戶直接地操做顯存,支持硬件覆蓋、內存與顯存反轉。DirectDraw在提供這些功能的同時並支持基於Microsoft Windows的應用程序和設備驅動。DirectDraw做爲一種軟件接口,支持Windows的GDI(圖像設備接口),並提供直接操做顯示設備的功能。它提供了與設備無關的遊戲、Windows子系統等軟件開發方式。 它還可以支持許多種顯示硬件,包括從簡單的SVGA顯示器到高級硬件性能(支持圖像剪切、延伸和非RGB顏色格式)。接口的設計使您的應用程序可以知道所使用硬件的特性,從而能夠支持它們的硬件加速功能。 關於DirectDraw,在之後還將有更加詳細的講解。 第五節 DirectSound Microsoft DirectSound的API是DirectX平臺軟件開發工具(SDK)程序員指南的聲音組件。DirectSound提供了硬件加速、對聲音設備的直接操做。在提供這些功能的同時,它還保持了與當前設備驅動的兼容性。 新版本的DirectSound可以在運行中查詢硬件性能以肯定最優的操做方式,還具備抓獲聲音、低延遲混音等功能特性。它的新功能還包括支持屬性集(Porperty Sets),從而即便DirectSound不直接支持新硬件的特性,它也可以利用並受益。 DirectSound是經過「硬件抽象層(HAL)」來操做聲音硬件的,這是一個由聲音設備驅動來實現的接口。HAL提供瞭如下功能: 要求和釋放對聲音硬件的控制; 描述聲音硬件的特性; 在硬件容許的條件下實現特定的操做; 在硬件不容許的時候報告操做失敗。 DirectSound可以自動地利用硬件加速,包括硬件混音和硬件聲音緩衝。您的應用程序無須查詢硬件和程序特性,而能夠在運行期部分查詢DirectSound來得到對聲音設備特性的充分描述,而後根據各個特性的存在或缺乏來使用不一樣的方法進行優化。您還能夠指定接受硬件加速的聲音緩衝區。 下圖顯示了DirectSound與系統中其它聲音組件的關係:   關於DirectSound,在之後還將有更加詳細的講解。 第六節 DirectPlay DirectPlay的主要做用在於使應用程序間通信方式得以簡單化。DirectPlay的技術不只提供了一個方案,實現了通信與傳送協議及在線服務的無關性,並且還實現了與傳輸服務器和遊戲服務器的無關性。萬一所基於的網絡不支持某一方式,DirectPlay包含了必要的代碼來仿效它。 DirectPlay的service provider結構使應用程序與網絡隔絕開來。應用程序經過查詢DirectPlay來得到所基於網絡功能特性(例如延遲、帶寬等),從而相應地調整通信方式。下面的圖顯示了DirectPlay service provider的結構:    使用DirectPlay的第一步是選擇使用哪種service provider,它決定了將用於通信的網絡或協議。協議能夠是遍及Internet的TCP/IP、局域網中的IPX或兩臺計算機間的鏈接電纜。 DirectPlay提供了兩種頗有用的鏈接管理方式: IDirectPlay3::EnumConnections列舉了應用程序能夠得到的全部鏈接; IDirectPlay3::InitializeConnection初始化一種特定的鏈接。 在肯定了網絡的鏈接後,爲了方便理解下面的內容,先來看看這樣幾個概念: 首先從session講起。DirectPlay session是若干臺計算機之間的通信通道。一個應用程序只有在成爲了某個session的一部分後纔可以開始與其它計算機進行通信。有兩種方法能夠實現:列舉一個網絡中
相關文章
相關標籤/搜索