《Windows游戏编程大师技巧》三、Windows高级编程
生活随笔
收集整理的這篇文章主要介紹了
《Windows游戏编程大师技巧》三、Windows高级编程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
使用資源
資源就是你的程序代碼結合在一起的多塊數據,可以被程序本身在運行時加載。 資源應當也放在程序的.EXE文件中的原因是:
1.同時包含代碼和數據的.EXE文件更容易發布。 2.外力不容易任意刪改程序的數據文件(如.BMP和.WAV文件)。
對于想編譯進程序中的數據類型沒有限制,下列這些預定義的資源類型就可以 滿足大部分需要:
圖標 - 小的位圖文件 光標 - 鼠標指針的位圖 字符串 - 可以硬編碼在代碼中,也可以集中放在這 聲音 - 大部分Windows程序都使用.WAV格式 位圖 - 這是標準的位圖,使用.BMP擴展名 對話框 - 也可以作為資源來存儲 圖元 - 一系列圖像操作記錄的回放
要添加資源文件,必須有一個以ASCII形式的資源描述文件.RC。編譯過程如下:
下面是如何在.RC腳本文件中定義一個ICON資源:
windowicon ICON star.ico (使用字符串) 124 ICON ship.ico ? ? ? ? ?(使用數字)
使用字符串定義時會產生歧義,windowicon可能是個字符串也可能是個#define定義的符號常量。 所以還需要一個.H文件來解析符號索引。
RESOURCES.H的內容:
#define ID_ICON1 100 #define ID_ICON2 101 #define ID_ICON3 102
RESOURCES.RC的內容:
#include "RESOURCES.H"
ID_ICON1 ICON star.ico ID_ICON2 ICON ball.ico ID_ICON3 ICON cross.ico
現在,將RESOURCES.RC和.ICO文件添加到工程,并在程序中#include RESOURCES.H。 若使用字符串定義,則:winclass.hIcon = LoadIcon(hInstance, "icon_name"); 若使用符號索引,則:winclass.hIcon =?LoadIcon(hInstance, MAKEINTRESOURCE(ID_ICON1)); 注意第一個參數不再是NULL而是hInstance。
其他資源也都是類似這樣定義和使用的。 光標:LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR1)); 字符串表:LoadString(hInst, IDS_STRING109, string3, 20);
GDI簡介
應該了解GDI,以便知道如何在不使用DirectX的情況下如何在Windows環境繪制各種圖形。 而理解WM_PAINT消息對于標準的GDI圖形和Windows編程來講是非常重要的,因為大部分 Windows程序的顯示都圍繞該消息。例外是游戲編程中DirectDraw或Direct3D負責圖形繪制。
PAINTSTRUCT ps; ? ? // used in WM_PAINT HDC hdc; ? ? ? ? ? ? ? ? // handle to a device context case WM_PAINT: { // simply validate the window hdc = BeginPaint(hwnd, &ps); // do all your painting here EndPaint(hwnd, &ps); // return success return (0); }
參看下面圖示,當一個窗口被移動、改變大小或被其他窗口“弄臟”時,該窗口的用戶區的 部分或全部需要重畫。這時,WM_PAINT消息就被發送了。
對BeginPaint()和EndPaint()函數的調用可以完成一系列任務。首先,它們使用戶區有效; 其次,它們用該窗口創建時參照的Windows類中定義的背景刷來填充該窗口的背景。
你只能訪問實際上需要刷新的該窗口用戶區的一部分。無效矩陣區域的坐標都保存在 BeginPaint()函數返回值PAINTSTRUCT的rcPaint字段中。如果要訪問整個用戶區的話, 這就是一個問題。解決方法是通過GetDC()直接獲得圖形設備描述表。
但BeginPaint()-EndPaint()會向Windows發消息指示窗口有效,而GetDC()-ReleaseDC()不會, 所以WM_PAINT消息將一直不停地傳遞下去,因為必須使該窗口有效。因此在ReleaseDC() 后還要調用ValidateRect()。
PAINTSTRUCT ps; HDC hdc; RECT rect; case WM_PAINT: { // simply validate the window hdc = GetDC(hwnd); // do all your painting here ReleaseDC(hwnd, hdc); // get client rectangle of window GetClientRect(hwnd, &rect); // validate window ValidateRect(hwnd, &rect); // return success return(0); }
注意GetClientRect是用來獲取用戶矩形區域的坐標。每個窗口都有兩套坐標系: Windows坐標系和用戶坐標系。區別見下圖:
你很可能會說:“非得這么麻煩嗎”是的,非得如此,因為這是Windows。哈哈! 本書的大多數例程里,將在WM_PAINT消息以外的地方使用GetDC()-ReleaseDC(), BeginPaint()-EndPaint()只用于WM_PAINT消息句柄中。
基本文本顯示
Windows有最復雜且最強悍的文本渲染系統。當實際運用在實時游戲中時,用GDI文本 引擎輸出文本就顯得太慢了,還是要親手設計基于DirectX的文本引擎。但先了解下有助于 調試和輸出。
輸出文本有兩個常用函數:TextOut()和DrawText()。TextOut()是一個寒酸的文本輸出函數, 而DrawText()則像凌志汽車一樣豪華。我經常使用TextOut()因為它運行比較快。
case WM_PAINT:?{
?????????????? hdc = BeginPaint (hwnd, &ps) ;
?????????????? GetClientRect (hwnd, &rect) ;
?????????????? ???
? ? ? ? ? ? ? ?char buffer[50];
? ? ? ? ? ? ? ?static int counter = 0;
? ? ? ? ? ? ? ?sprintf(buffer, "WM_PAINT called %d times ", ++counter);
? ? ? ? ? ? ? ?TextOut(hdc, rect.left, rect.top, buffer, strlen(buffer));
? ? ? ? ? ? ? ?DrawText (hdc, TEXT (“Hello text”), -1, &rect,
??????????????????? DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;? ? ? ? ? ? ? ?
?????????????? EndPaint (hwnd, &ps) ;
?????????????? return 0 ; }
==========================================================
2012年4月22日 更新
補充學習處理重要事件:Window操作、鍵盤操作、鼠標操作。
1.Window操作
WM_CLOSE消息在WM_DESTROY和WM_QUIT之后發送,它表示用戶正試圖關閉窗口。 如果在WinProc()里僅return (0),那么用戶不能關閉窗口。WM_SIZE消息對于窗口游戲 非常重要,當窗口尺寸改變時,必須調整圖像顯示來適應。
2.鍵盤操作
在Windows環境下,可以以多種方式訪問鍵盤消息: 2.1 通過WM_CHAR消息:保存產生的ASCII碼,如'a'或'A',字處理程序要關心這個。 2.2 通過WM_KEYDOWN/UP消息:保存產生的掃描碼,即鍵盤上每一個按鍵的編碼, 如ESC鍵VK_ESCAPE。游戲只需關心WASD移動,F開火而不必關心產生的是大寫字符 還是小寫字符,所以不必關心WM_CHAR消息。 2.3 通過調用GetAsyncKeyState():在狀態表中跟蹤該鍵的最后已知狀態,使用它的 妙處是它與事件循環沒有耦合,可以在任何地方測試按鍵。
3.鼠標操作
鼠標移動事件WM_MOUSEMOVE。lParam保存鼠標位置,wParam保存按鍵狀態。
case WM_MOUSEMOVE: { int mouse_x = (int) LOWORD(lParam); int mouse_y = (int) LOWORD(lParam); int buttons = (int) wParam; if (buttons & MK_LBUTTON) ... if (buttons & MK_RBUTTON) ... } break;
鼠標只是移動沒有按鍵產生的事件。
case WM_LBUTTONDBLCLK: { int mouse_x = (int) LOWORD(lParam); int mouse_y = (int) LOWORD(lParam); ? ? ?... // tell windows you handled it return (0); } break;
4.自行發送消息
自行傳遞消息有兩種方法: SendMessage()向窗口傳遞一個要求立即處理的消息。 PostMessage()將消息發往窗口的消息隊列。
為什么要自行發送消息?因為Window的設計者希望你這樣做,這也是窗口環境下的工作原理。 下一章中學習按鍵控件時將會看到,發送消息是和控件窗口交流的唯一途徑!
轉載于:https://www.cnblogs.com/xiaomaohai/archive/2012/04/18/6157844.html
總結
以上是生活随笔為你收集整理的《Windows游戏编程大师技巧》三、Windows高级编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拍个黄瓜竟然被罚5000元?到底冤不冤?
- 下一篇: 日本2024年将进行首例“飞行汽车”载人