送給初學者的禮物:遊戲程式設計起源連載二(轉)
送給初學者的禮物:遊戲程式設計起源連載二(轉)[@more@] 三、建立視窗 好訊息,建立視窗你所要做的只是呼叫一個CreateWindowEx()函式。壞訊息是,這個函式有好多的引數。以下便是函式原形: HWND CreateWindowEx( DWORD dwExStyle, // extended window style LPCTSTR lpClassName, // pointer to registered class name LPCTSTR lpWindowName, // pointer to window name DWORD dwStyle, // window style int x, // horizontal position of window int y, // vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window HMENU hMenu, // handle to menu, or child-window identifier HINSTANCE hInstance, // handle to application instance LPVOID lpParam // pointer to window-creation data ); 首先:函式的返回值。也就是函式的型別。是不是所有建立視窗用的函式的型別的討厭樣子都感覺親切了一點兒?不要緊,你會習慣的,肯定比你想象的速度要快。這裡返回的型別是HWND,是一個視窗的控制程式碼(控制程式碼就是視窗的識別符號)。你將把CreateWindowEx()的返回值傳遞給一個視窗的控制程式碼,就像一個引數一樣。現在,我們來琢磨一下這些引數,很多根據名字就知道它是幹什麼的了。 ※ DWORD dwExStyle:擴充的視窗風格。你將很少使用擴充的視窗風格,所以多數時間你會把它設定為NULL。如果有興趣,查一下幫助檔案,可以一試由WS_EX_打頭的擴充風格。 ※ LPCTSTR lpClassName:還記得你的視窗類的名稱嗎?再用一次。 ※ LPCTSTR lpWindowName:將顯示在視窗的標題欄裡的簡短文字。 ※ DWORD dwStyle:視窗的風格。它將允許你詳細的描繪你所要建立的視窗的風格。有很多風格你可以利用哦,都是以WS_打頭的,你可以利用(|)符號組合利用它們。我將在這兒介紹幾個常用的。 ◎ WS_POPUP 指定一個彈出的視窗。 ◎ WS_OVERLAPPED 指定一個具有標題欄和邊界的重疊視窗。 ◎ WS_OVERLAPPEDWINDOW 指定一個具有所有標準控制元件的視窗。 ◎ WS_VISIBLE 指定一個初始時可見的視窗。 看得出,WS_OVERLAPPEDWINDOW是一個組合體。簡單的說,你可以按照如下規律:如果你要建立一個可以最大化、最小化、隨意改變大小等等地視窗,就選擇WS_OVERLAPPEDWINDOW;如果你只想要一個具有標題欄、可改變大小的視窗,就選擇WS_OVERLAPPED;如果你只想要一個光禿禿的視窗,就選擇WS_POPUP;如果你只想顯示一個黑色的大方框,可能你要用它寫一個全屏的遊戲,選擇WS_VISIBLE是沒錯的。 ※ int x,y:你所要建立的視窗的左上角的座標。 ※ int nWidth,nHeight:猜也猜到了,是視窗的長和高。 ※ HWND hWndParent:指向父視窗的控制程式碼。你若想在視窗下再建立一個視窗,那麼第一個視窗就叫父視窗。我們先建立一個主視窗,所以設定為NULL,也就意味著Windows桌面是父視窗。 ※ HMENU hMenu:這是用在視窗上的選單控制程式碼。若你學會建立和使用資源,即建立自己的選單,你可以用LoadMenu()函式呼叫自己的選單資源。目前,先設為NULL。 ※ HINSTANCE hInstance:是一個名柄,它指向由Windows傳遞給WinMain()的例項。 ※ LPVOID lpParam:對於遊戲程式設計來說,沒有什麼用的東西,只有簡單的視窗程式用到它。設定為NULL好了。 我們現在萬事具備,東風也有了。我先給個示例: HWND hwnd; if (!(hwnd = CreateWindowEx(NULL, // extended style, not needed "Sample Class", // class identifier "Sample Window", // window title WS_POPUP | WS_VISIBLE,// parameters 0, 0, 320, 240, // initial position, size NULL, // handle to parent (the desktop) NULL, // handle to menu (none) hinstance, // application instance handle NULL))) // who needs it? return(0); 你可能會在遊戲程式設計中用上這這段程式碼,因為它是一個彈出式視窗。注意,我用了if形式,目的是一旦CreateWindowsEX()函式失靈,返回一個NULL,也就意味著如果視窗由於某種原因不能被建立,那麼WinMain()就被簡單的返回,程式結束。現在我們學會了足夠的知識建立一個小有功能的視窗了。還記得我們建立視窗類“sample class”時,一個指向“CALLBACK”型別函式的指標嗎?對,是“lpfnWndProc”。要想讓你的視窗真正做點事兒,我們還得來處理一下它指向的“視窗過程”函式。 四、顯示視窗 CreateWindowEx()從內部建立視窗,但並不顯示它。要顯示這個視窗,必須呼叫另外兩個函式:ShowWindow()和UpdateWindow()。頭一個設定視窗的顯示狀態,後一個則更新視窗的客戶區。對於程式的主視窗,ShowWindow()必須被呼叫一次,呼叫程式碼如下: ShowWindow(hwnd,nCmdShow); 第一個引數是由CreateWindowEx()函式返回的視窗控制程式碼;第二個引數就是視窗的顯示模式引數,在☆WinMain()函式中提到過,就不重複了。UpdateWindow()函式的呼叫程式碼如下: UpdateWindow(hwnd); 引數hwnd同ShowWindow()函式的hwnd一樣。 五、訊息的處理 我已經說過訊息在視窗裡的作用了,下面讓我們來仔細學習一下它。處理訊息的函式結構如下: LRESULT CALLBACK MsgHandler( HWND hwnd, // window handle UINT msg, // the message identifier WPARAM wparam, // message parameters LPARAM lparam // more message parameters ); 這個LRESULT型別要求返回一個32位的整數。實際取值依賴於訊息,但是這個值很少在應用程式程式碼中得到應用。以前我們談到過一點CALLBACK協定,它的引數很簡單: ※ HWND hwnd:是接收訊息的視窗的控制程式碼,也是由CreateWindowEx()函式返回的控制程式碼。 ※ UINT msg:這是一個訊息識別符號,都是以WM_打頭的符號常量,意思是“Windows Message”。很多的,這裡只介紹一些常用的: ◎ WM_ACTIVATE:一個新視窗被啟用。 ◎ WM_CLOSE:一個視窗被關閉。 ◎ WM_COMMAND:一個選單功能被選擇。 ◎ WM_CREATE:一個視窗被建立。 ◎ WM_LBUTTONDBLCLK:滑鼠左鍵被雙擊。 ◎ WM_LBUTTONDOWN:滑鼠左鍵被按下。 ◎ WM_MOUSEMOVE:滑鼠被移動。 ◎ WM_MOVE:一個視窗被移動。 ◎ WM_PAINT:視窗的一部分需要重畫。 ◎ WM_RBUTTONDBLCLK:滑鼠的右鍵被雙擊。 ◎ WM_RBUTTONDOWN:滑鼠的右鍵被按下。 ◎ WM_SIZE:視窗的大小被改變。 ◎ WM_USER:做你想做的。 ※ WPARAM wparam,LPARAM lparam:訊息引數。它們提供有關訊息的附加資訊,這兩個值對於每條訊息來說都是特定的。 你要把所有要發生的訊息都寫程式序程式碼的話,我想你可能已經累瘋了。我想我會的。感謝上帝,Windows提供了預設訊息處理,如果你沒有任何特殊的訊息需要處理了,你總是要用DefWindowPorc()函式的,下面給一個最簡單的例子,沒有任何特定的訊息要處理的例子: LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { return(DefWindowProc(hwnd, msg, wparam, lparam)); } 簡單吧!但通常你都需要處理一些自己的訊息,你要寫自己的程式程式碼,然後返回0,來告訴程式你幹完了。下面是一個例子,當視窗建立時,你呼叫了一個初始化的函式Initialize_Game(),然後返回0,最後告訴程式自己處理那些預設的訊息吧: LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (msg == WM_CREATE) { Initialize_Game(); return(0); } return(DefWindowProc(hwnd, msg, wparam, lparam)); } 你很可能需要一個“switch”結構來手動完成你想要控制的訊息,然後把剩下的交給DefWindowProc()去做。大功告成前,我不得不提醒您一件事,就是怎樣使你的訊息控制得到響應呢? 六、讀取訊息佇列 這裡先給你一個switch結構的例子吧: LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch(msg) { case WM_CREAT: [初始化遊戲] return 0; case WM_PAINT: [畫一架飛機] return 0; case …………………… …………………… } return(DefWindowProc(hwnd, msg, wparam, lparam)); } 在進入程式的主迴圈前,你需要看看你的訊息控制(就是你在switch結構裡編的那些),尤其是還沒有用到的訊息控制是否被機器存了起來,以備一旦用到,馬上響應。做到正確的響應,你需要做幾件事。首先你需要PeekMessage()函式。下面是它的原形: BOOL PeekMessage( LPMSG lpMsg, // pointer to structu
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951677/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 開學送給她的禮物(Python實現)Python
- 程式設計師給女友最好的禮物是....程式設計師
- iOS 直播間送禮物邏輯(禮物連擊)iOS
- 給程式設計初學者的一份Java入門指南,課程禮包,請自取程式設計Java
- 給Python初學者的一些程式設計技巧Python程式設計
- 一份送給Java初學者的指南Java
- 送給程式設計師們的經典電子書大禮包程式設計師
- 迴歸初心,《原始征途》是送給征途玩家的禮物
- mySQL初學者通過eclipse程式設計程式碼連結,載入驅動,拿到資料MySqlEclipse程式設計
- 【USACO題庫】 Greedy Gift Givers貪婪的禮物送禮者c++C++
- 遊戲史記(一):上帝的禮物遊戲
- 獻給 Dapper 使用者的一份禮物APP
- 【二分】華華給月月準備禮物
- 1024程式設計師的節日,千鋒給你一份不一樣的禮物程式設計師
- 全網預約2000萬,這款手遊是十二歲的光子送給世界的新禮物
- 尋找程式設計師界的至尊王者,有一份神祕大禮要送給你!程式設計師
- 通訊框架 t-io 學習——給初學者的Demo:ShowCase設計分析框架
- YouGov:40%的父母計劃花更多錢購買遊戲禮物Go遊戲
- 從初學者到程式設計高手,幾種必學的程式語言程式設計
- 遊戲化設計(二):利於遊戲心理學,讓使用者愛上你的產品遊戲
- 給初學者的Web安全指南Web
- 給初學者的 fc 示例教程
- 給初學者的 type 命令教程
- 學姐的禮物
- “520”送花還是送禮物?船到都能送!
- 初學者學習Java程式設計的基礎書籍推薦Java程式設計
- ABAP初學者如何系統地學習ABAP程式設計?程式設計
- 送給CSS初學者的懸停過渡動畫三部曲CSS動畫
- 寫給大資料開發初學者的話 | 附教程(轉)大資料
- 《魔物娘》遊戲設計分析遊戲設計
- 給初學者看的 shuf 命令教程
- [譯] 給初學者的 Jupyter Notebook 教程
- 網路程式設計初學程式設計
- 給予程式設計者的雞湯文程式設計
- 給初學者的RxJava2.0教程(三)RxJava
- 給初學者的RxJava2.0教程(七)RxJava
- 給初學者的 RxJava2.0 教程 (四)RxJava
- 寫給初學者的Linux餐前小菜Linux
- C語言程式設計,初學者必學程式碼規範,你知道哪些?C語言程式設計