遊戲開發新手入門之Windows程式設計(轉)

post0發表於2007-08-12
遊戲開發新手入門之Windows程式設計(轉)[@more@]

  開始

  

  多數的Windows程式都需要Windows.h和Windowsx.h這兩個標頭檔案,要確保使用它們。當然,你還需要其它的標準的C的標頭檔案,象stdio.h,conio.h等。除了這些,你還會經常看到在程式的開始有這樣一行程式碼:

  

  #define WIN32_LEANAND_MEAN

  

  它表示Windows的標頭檔案中將拒絕接受MFC的東西,這將加速你的build時間。如果你從沒有打算應用MFC在你的遊戲程式設計中,那就使用它吧。如果你以前從沒有看過這種宣告型別――在#define後,直接加上一個“單詞”,那麼它的作用就是有條件編譯。看看下面的例子:

  

  #ifdef DEBUG_MODE

  printf("Debug mode is active!");

  #endif

  

  意思是:如果程式的開始包含#define DEBUG_MODE,那麼就printf(),否則退出。這個對於你跟蹤程式的邏輯錯誤是很有幫助的。

  

  WinMain()函式

  

  DOS下的C語言從main()開始,Windows下的C語言從WinMain()開始,一個空的WinMain()函式是這樣的:

  

  int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

  {

  return(0);

  }

  

  一個函式即使什麼也沒做,也應該返回一個值。是的,有好多東西我們不熟悉。首先的首先,WINAPI是個什麼宣告?WINAPI是在windows.h標頭檔案中定義的一個宏,它把函式呼叫翻譯成正確的呼叫約定。當我們在程式中需要用到組合語言的時候,我們在來深究它好了,記住,如果要用WinMain(),就必須要有WINAPI。

  

  下一步讓我們來看看括號裡的四個引數:

  

  ◎ HINSTANCE hinstance:HINSTANCE是一個控制程式碼型別的識別符號。變數hinstance是一個整數,用於標識程式例項。Windows設定這個引數的值,並把它傳遞給你的程式程式碼。很多Windows函式都要用到它。

  

  ◎ HINSTANCE hPreInstance:你不用擔心這個引數,它已經被廢掉了。它只是為古老的Windows版本服務的。你將還會看到類似的情況。

  

  ◎ LPSTR lpCmdLine:是一個指向字串的指標,它僅在程式名是從DOS命令列輸入或是從Run對話方塊中輸入時才起作用。因此,很少被程式程式碼所用。

  

  ◎ int nCmdShow:決定了視窗在初始顯示時的狀態。Windows通常給這個引數分配一個值。通常是SW_打頭的一個常量。例如SW_SHOWNORMAL表示預設狀態,SW_MAXINIZE或SW_MINIMIZE分別表示最大和最小模式等等。

  

  訊息

  

  當你在DOS下程式設計的時候,你不必擔心其它程式的執行,因為DOS是獨佔模式。但你在Windows平臺上程式設計時,你不得不考慮其它正在執行的程式。鑑於此,Windows透過“訊息”來連線操作申請和具體操作。簡單的說,就是我們指示程式或程式本身向Windows發出諸如移動視窗、放大視窗、關閉視窗等地申請,Windows再根據申請,考察實地情況,拒絕或發出指令,讓程式(計算機)作出相應的動作。再例如,滑鼠隨時向Windows發出訊息,彙報游標位置,左鍵或右鍵是否按下等,Windows再根據訊息作出相應的反應。總之,無論何時,Windows都要隨時掌控所有的訊息,而且,Windows是一直不斷地接收到各種訊息。

  

  這種功能是透過一種被命名為CALLBACK函式型別實現的。不用害怕,訊息的傳遞來,傳遞去都是由Windows自己完成的,你只要宣告一個CALLBACK函式就可以了,就像WINAPI用在WinMain()前一樣。如果還沒有明白,不要緊,往下看你就明白了。現在,我要離開這個話題一會,因為你只有先建立視窗(Windows),傳遞訊息才有可能實現。

  

  視窗類

  

  現在談論一點C++的知識,因為要想建立一個視窗,你就得先建立一個視窗類。視窗類包含所有的有關視窗的資訊,如用什麼樣的滑鼠符號,選單樣式等等。開發任何一個視窗程式,都離不開視窗類的建立。為了達到此目的,你必須填寫WNDCLASSEX結構。EX的意思是“擴充”的意思,因為有一個老的結構叫作WNDCLASS,這裡,我們將使用WNDCLASSEX結構,它的樣子如下:

  

  typedef struct _WNDCLASSEX {

  

  UINT cbSize;

  UINT style;

  WNDPROC lpfnWndProc;

  int cbClsExtra;

  int cbWndExtra;

  HANDLE hInstance;

  HICON hIcon;

  HCURSOR hCursor;

  HBRUSH hbrBackground;

  LPCTSTR lpszMenuName;

  LPCTSTR lpszClassName;

  HICON hIconSm;

  } WNDCLASSEX;

  

  這個結構有不少成員,討厭的是,你必須為視窗類設定每一個成員。莫發愁,紙老虎一個。讓我們來個速成。

  

  ※ UINT cbSize:指定了以位元組為單位的結構的大小。這個成員是透過sizeof(WNDCLASSEX)實現的。你將會經常看到它,尤其是你使用了DirectX。

  

  ※ UINT style:指定了視窗的風格。它經常被以CS_打頭的符號常量定義。兩種或兩種以上的風格可以透過C語言中的“或”(|)運算子加以組合。大多數情況我們只應用四種風格,出於對文章長度的考慮,我們只列出這四種。若你還需要其它的,到MSDN裡找一下好了。別告訴我你用的不是Visual C++啊!

  

  ◎ CS_HREDRAW:一旦移動或尺寸調整使客戶區的寬度發生變化,就重新繪製視窗。

  

  ◎ CS_VREDRAW:一旦移動或尺寸調整使客戶區的高度發生變化,就重新繪製視窗。

  

  ◎ CS_OWNDC:為該類中的每一個視窗分配一個唯一的裝置上下文。

  

  ◎ CS_DBLCLKS:當使用者雙擊滑鼠時向視窗過程傳送雙擊訊息。

  

  ※ WNDPROC lpfnWndProc:是指向視窗過程的指標。一般都指向CALLBACK函式。如果你沒有用過函式指標,簡單理解為函式的地址就是函式的名字,名字後面別帶括號。

  

  ※ int cbClsExtra:它是為類保留的額外資訊 。大多數程式設計師不用它,你在在寫遊戲程式時也不太可能用它,所以,設為0好了。

  

  ※ int cbWndExtra:同上一個差不多,設為0好了。

  

  ※ HANDLE hInstance:是指向視窗過程例項的控制程式碼。同時也是WinMain()函式的引數之一。應該設定為hinstance。

  

  ※ HICON hIcon:指向視窗圖示的控制程式碼,它通常被LoadIcon()函式設定。在你學會如何在你的程式中使用資源前,你先設定成如下樣子:LoadIcon(NULL,IDI_WINLOGO)。當然,還有一些其它的IDI_打頭的符號常量,你自己去幫助檔案裡找吧。

  

  ※ HCURSOR hCursor:指向視窗游標的控制程式碼,它通常被LoadCursor()函式設定,在你學會如何在你的程式中使用資源前,你先用Windows預設的吧,LoadCursor(NULL,IDC_ARROW)。

  

  ※ HBRUSH hbrBackground:當你的視窗過程得到訊息,要求重新整理(或重畫)視窗時,至少要用一種純色或“brush”(畫刷)重畫視窗區域,畫刷是由引數確定的。你可以使用GetStockObject()函式呼叫幾種常備的畫刷,如BLACK_BRUSH, WHITE_BRUSH, GRAY_BRUSH等。現在,你就用GetStockObject(BLACK_BRUSH)吧。對不起,你可能覺得我說的太簡單了,但我不想把開始弄得太複雜。我在以後的篇幅裡會詳細講的,我保證。

  

  ※ LPCTSTR lpszMenuName:如果你想建立一個有下拉選單的視窗,你得給這個引數賦一個選單名稱(這涉及到資源),由於你還不知道怎麼建立選單,你就先用NULL設定成一個沒有選單的視窗吧。

  

  ※ LPCSTR lpszClassName:很顯然,你需要給類起個名字,隨你便,如“**”。要用雙引號引上啊!

  

  ※ HICON hIconSm:指向小圖示的控制程式碼。小圖示用來顯示在視窗的標題欄裡。要用到LoadIcon()函式,現在,你就用Windows預設的吧,LoadIcon(NULL,IDI_WINLOGO)。

  

  好了,你關於WNDCLASSEX結構知道的差不多了,你可以自己設定它了。下面是一個例子:

  

  WNDCLASSEX sampleClass; // declare structure variable

  sampleClass.cbSize = sizeof(WNDCLASSEX); // always use this!

  sampleClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; // standard settings

  sampleClass.lpfnWndProc = MsgHandler; // we need to write this!

  sampleClass.cbClsExtra = 0; // extra class info, not used

  sampleClass.cbWndExtra = 0; // extra window info, not used

  sampleClass.hInstance = hinstance; // parameter passed to WinMain()

  sampleClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Windows logo

  sampleClass.hCursor = LoadCursor(NULL, IDC_ARROW); // standard cursor

  sampleClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // a simple black brush

  sampleClass.lpszMenuName = NULL; // no menu

  sampleClass.lpszClassName = "Sample Class" // class name

  sampleClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // Windows logo again

  ......

  

  我想,你已經有點兒不太崇拜Windows程式設計師了。言歸正傳,有一點我得提醒你,注意函式GetStockObject()前的(HBRUSH)型別配置,這是因為GetStockObject()可以呼叫其它的物件,不僅僅是“brush”,所以你需要一個HBRUSH型別配置。在Visual C++舊版本里不用配置,但新的6.0版本需要它,否則會編譯出錯。

  

  下一件事是註冊這個視窗類,只有這樣,你才能建立新的視窗。十分簡單,你只需要呼叫一個RegisterClassEX()函式,它只有一個引數,就是你的視窗類的地址(名字),根據我上面給的例子,這裡應該這樣:

  

  RegisterClassEx(&sampleClass);

  

  嗨,我們的視窗類建立完了,我們可以用它建立一個視窗了。只是時間問題嘍!

  

  建立

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951578/,如需轉載,請註明出處,否則將追究法律責任。

相關文章