(DOC)高級Windows編程_第1頁
(DOC)高級Windows編程_第2頁
(DOC)高級Windows編程_第3頁
(DOC)高級Windows編程_第4頁
(DOC)高級Windows編程_第5頁
已閱讀5頁,還剩83頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、高級Windows編程 高級Windows編程 在火箭專家看來,Windows編程當(dāng)然算不上什么大工程。但Windows 編程很絕的地方在于,你不用了解太多細(xì)節(jié),就可以完成很多工作。因此,我們在本章中將主要討論開發(fā)一個完整的Windows應(yīng)用程序所需要的一些最重要的內(nèi)容。本章主要內(nèi)容有: Q 使用資源(如圖標(biāo)、光標(biāo)和聲音)Q 菜單Q 基本的圖形設(shè)備接口和視頻系統(tǒng)Q 輸入設(shè)備Q 傳遞消息使用資源Windows創(chuàng)建者提出的一個主要設(shè)計目標(biāo)就是,在一個Windows應(yīng)用程序中除程序代碼外還能儲存更多的資源(甚至Mac程序也是如此)。他們認(rèn)為一個程序的數(shù)據(jù)也能夠駐留在該程序的.EXE文件中。這是個不錯

2、的想法,因為: 一個同時含有代碼和數(shù)據(jù)的.EXE文件更容易分配。 如果沒有外部數(shù)據(jù)文件的話,就不會丟失這些數(shù)據(jù)。 外部強制轉(zhuǎn)移不會很容易地訪問、任意刪改、添加、和分配你的數(shù)據(jù)文件(例如,.BMP文件、.WAV文件等等)。要滿足這種數(shù)據(jù)庫技術(shù),Windows程序支持該種功能,稱之為資源。這只是與你的程序代碼結(jié)合在一起的數(shù)據(jù)的一小部分,這部分?jǐn)?shù)據(jù)在以后的運行過程中可被程序本身加載。圖X 第3章 高級Windows 編程 X3.1解釋了這個概念。Windows應(yīng)用程序.EXE程序代碼數(shù)據(jù)資源圖標(biāo)位圖.wavs光標(biāo)字串表對話框菜單 .EXE文件后部定位的 資源 圖3.1 資源和Windows應(yīng)用程序的

3、關(guān)系那我們討論的是哪一種資源呢?實際上對于想編譯進(jìn)程序中的數(shù)據(jù)類型并沒有什么限制,因為Windows程序支持用戶定義的資源類型。但是應(yīng)當(dāng)注意幾種預(yù)定義的類型: 圖標(biāo)小位圖圖形,可以用于許多方面,例如單擊該圖形運行一個目錄下的一個程序。圖標(biāo)使用.ICO文件擴展名。 光標(biāo)一個表示鼠標(biāo)指針的位圖。Windows允許以各種方式操作光標(biāo)。例如,可以令光標(biāo)在窗口之間移動時變換。光標(biāo)使用.CUR文件擴展名。 字符串字符串資源對于作為一種資源來講可能是最不明顯的了。可以這樣說:“我經(jīng)常將字符串添加到我的程序中或者一個數(shù)據(jù)文件中。”我知道你的意思。然而,Windows允許將一個字符串表作為一種資源放到你的程序中

4、,并且通過標(biāo)識符 來訪問它們。 聲音大部分Windows程序至少都可以通過.WAV文件來使用聲音。因此,.WAV文件也是一種資源。 位圖這是標(biāo)準(zhǔn)的位圖,可以是單色、4位、8位、16位或32位格式的像素矩陣。在圖形操作系統(tǒng)(如Windows)中是非常常用的對象,因此也可以將位圖作為一種資源。位圖使用.BMP文件擴展名。 對話框?qū)υ捒蛟赪indows中也非常常用,設(shè)計者可以讓對話框作為一種資源,而不是在外部裝載的東西。好主意!因此,你可以在程序中創(chuàng)建對話框,也可以將它們設(shè)計為一個編輯器,作為一種資源來存儲。 圖元文件圖元文件相對高級。它們允許將一個圖像操作作為一個序列記錄在一個文件中,然后再回放它

5、?,F(xiàn)在你已經(jīng)了解了資源的定義以及存在形式,下一步就是如何將它們一起使用。好!有 83X 游戲編程大師 X一個資源編譯器的程序,可以以一個擴展名為.RC的ASCII文本資源文件輸入。該文件是一個C/English文件描述了編譯到一個數(shù)據(jù)文件中的所有資源。該資源編譯器裝載所有的資源,以.RES的擴展名形式將所有資源放置在一個大數(shù)據(jù)文件中。這個.RES文件包含了你在.RC文件中定義的諸如圖標(biāo)、光標(biāo)、位圖、聲音等所有資源的二進(jìn)制數(shù)據(jù)。該.RES文件和.CPP、.H、.LIB、.OBJ等等文件一樣都可以編譯成一個.EXE文件,這就已經(jīng)足夠了!圖3.2顯示了該過程的數(shù)據(jù)流程的可能性。資源資源編譯器 資源腳

6、本資源編譯器通常構(gòu)入編譯器中 編譯器連接器 圖3.2 編譯和連接過程中資源的數(shù)據(jù)流集合資源以前可以使用一個外部資源編譯器,如RC.EXE將所有的資源編譯到一起。但是現(xiàn)在可以使用編譯器IDE來做這些工作。因此,如果在程序中添加一種資源的話,可以簡單地通過IDE中的“文件”菜單中選擇“新建”按鈕(大多數(shù)情況下),然后選擇想要添加的資源類型(后面將詳細(xì)討論)來添加資源。讓我們回顧一下如何處理資源:可以向程序中添加許多數(shù)據(jù)類型和對象,然后它們以資源的形式和實際程序代碼一起駐留在.EXE文件中(一般在文件的末尾某處)。在運行過程中,可以訪問這個資源數(shù)據(jù)庫,并且可以從程序本身(而不是作為一個單獨的文件從磁

7、盤中)裝載資源數(shù)據(jù)。要創(chuàng)建該資源文件,必須有一個以ASCII文本形式的資源描述文件,名稱為.RC。然后將該文件傳遞到編譯器中(一起訪問該資源),并且產(chǎn)生一個.RES文件。然后將該.RES文件和所有的其他程序?qū)ο筮B接到一起,創(chuàng)建一個最終的.EXE文件。就這么簡單!好,這樣我就變成了一個億萬富翁了。記住上述所有內(nèi)容,下面就讓我們討論一下眾多的資源對象,學(xué)會如何創(chuàng)建并裝載到程序中。我就不再重復(fù)上面提到過的所有的資源,但是你應(yīng)當(dāng)能夠指出任何其他的信息對象。84X 第3章 高級Windows 編程 X 它們都以相同的方式運行,產(chǎn)生或采用一個數(shù)據(jù)類型、句柄或熬一個通宵不休息的精神插曲。 使用圖標(biāo)資源使用資

8、源只需要創(chuàng)建兩個文件:一個是.RC文件,如果想在.RC文件中對符號標(biāo)識符進(jìn)行標(biāo)注的話,可能還需要創(chuàng)建一個.H文件。在下面內(nèi)容中將詳細(xì)討論。當(dāng)然,最后還需要產(chǎn)生一個.RES文件,但是我們讓IDE編譯器來做這個工作。作為一個創(chuàng)建圖標(biāo)資源的例子,讓我們看一下如何改變?nèi)蝿?wù)欄上的應(yīng)用程序使用的圖標(biāo)以及窗口本身的系統(tǒng)菜單的圖標(biāo)。如果你還記得的話,我們在Windows類的創(chuàng)建過程中使用下面代碼設(shè)置過這些圖標(biāo):winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

9、這兩行代碼為這些普通圖標(biāo)和小版本的圖標(biāo)加載默認(rèn)的應(yīng)用圖標(biāo)程序。實際上可以通過使用已經(jīng)編譯到一個資源文件中的圖標(biāo),將所需要的圖標(biāo)裝載到這些存取窗口中。 首先需要一個圖標(biāo),我已經(jīng)創(chuàng)建了一個很酷的圖標(biāo)用于本書中所有的應(yīng)用程序。該圖標(biāo)名為T3DX.ICO,如圖3.3所示。我使用了VC+5.0的圖形編輯器(如圖3.4所示)創(chuàng)建了該圖標(biāo)。當(dāng)然你可以使用任何你想使用的程序(只要該程序支持該種輸出類型)來創(chuàng)建圖標(biāo)、光標(biāo)和位圖等等。 圖3.3 T3DX.ICO圖標(biāo)位圖T3DX.ICO是32像素32像素,16位色彩。圖標(biāo)可以安排在從1616到6464的區(qū)域內(nèi),最高可以達(dá)到256色彩。但是大多數(shù)圖標(biāo)都是3232以及

10、16位色彩的,我們也采用這種格式。一旦你有了感興趣的、需要放入一個資源文件中的圖標(biāo),就需要創(chuàng)建一個資源文件來放置該圖標(biāo)。為了簡單起見,需要人工編寫。(請記住,IDE編譯器完全可以做這些工作,但是那樣的話,你就什么也學(xué)不到了,不是嗎?).RC文件包含所有資源的定義,也就是說在程序中可以使用多種資源。 注 意 在編寫任何代碼之前,我想指出關(guān)于資源的非常重要的一點。Windows可以使用ASCII文本字符串或者是整數(shù)標(biāo)識符來引用資源。在大多數(shù)情況下,你可以在.RC文件中同時使用這兩種方式,但是應(yīng)當(dāng)注意一些資源只允許使用其中的一種。無論是哪種情況,資源必須以稍微不同的方式來加載,并且如果涉及到標(biāo)識符的

11、話,在你的工程中必須包含一個另外的符號前后對照的.H文件。85X游戲編程大師X圖 3.4VC+5.0 圖形編輯器下面是如何在.RC 腳本文件中定義一個 ICON 資源: 方法 I 使用字符串名icon_name ICON FILENAME.ICO例如:windowicon ICON star.ico MyCoolIcon ICON cool.ico或者是 方法 II 通過整型標(biāo)識符icon_id ICON FILENAME.ICO例如:windowicon ICON star.ico 124 ICON ship.ico這是令人混亂的地方:注意方法 I 中根本沒有任何注解。這就是個問題了,容易給

12、你帶 來麻煩,因此要仔細(xì)聽。應(yīng)當(dāng)能注意到:ICON 定義的每一種方法的第一個例子看上去完全 一樣。 但是, 一個理解為 “windowicon” 而另一個是一個符號 windowicon。 , 這樣就導(dǎo)致在.RC 文件中必須包含一個附加文件,來定義符號常量。當(dāng)資源編譯器解析下面代碼時,windowicon ICON star.ico 86 X 第3章 高級Windows 編程 X 資源編譯器首先看一下已經(jīng)在include頭文件定義的符號。如果該符號存在,資源編譯器就通過整型標(biāo)識符來引用該符號所指向的資源。否則,資源編譯器就假定它是個字符串,通過字符串“windowicon”來引用ICON。因此

13、,如果想在.RC資源腳本中定義符號ICON的話,也需要一個.H文件來解析該符號索引。要想在.RC腳本中包含.H文件,應(yīng)當(dāng)使用標(biāo)準(zhǔn)C/C+ #include描述符。例如,假定你想在.RC文件RESOURCES.RC中定義三個符號圖標(biāo),同時也需要一個.h文件RESOURCES.H。下面是每個文件的內(nèi)容:RESOURCES.H的內(nèi)容: #define ID_ICON1 100 / these numbers are arbitrary#define ID_ICON2 101#define ID_ICON3 102 RESOURCES.RC的內(nèi)容: #include “RESOURCES.H”/ he

14、re are the icon defines,note the use of C+ commentsID_ICON1 ICON star.icoID_ICON2 ICON ball.icoID_ICON3 ICON cross.ico 就是這樣。然后可以將RESOURCES.RC添加到你的工程中,確認(rèn)應(yīng)用程序文件中有#include RESOURCES.H,然后你就大功告成了。當(dāng)然,.ICO文件必須放在工程的工作目錄下,以便于資源編譯器能夠找到它們。如果沒有為圖標(biāo)定義(#define)符號,也沒有包含一個.H文件,資源編譯器將只能假定符號ID_ICON1、ID_ICON2和ID_ICON3是

15、字符串。然后就是如何在程序“ID_ICON1”、“ID_ICON2”和“ID_ICON3”中引用它們。我已經(jīng)完全打亂了所論及問題的時間/空間連續(xù)性,讓我們回顧一下想做的工作僅僅是加載一個簡單的圖標(biāo)。要想通過字符串名來裝載一個圖標(biāo),按下面步驟進(jìn)行:在.RC文件中:your_icon_name ICON filename.ico在程序代碼中: / Notice the use of hinstance instead of NULL。87X 游戲編程大師 XWinclass.hIcon = LoadIcon(hinstance, “your_icon_name)”;Winclass.hIconSm

16、 = LoadIcon(hinstance, “your_icon_name)”; 要通過符號參考來裝載,可以如前面例子#include 那些包含符號參考的頭文件。在.H文件中: #define ID_ICON1 100 / these mumbers are arbitrary#define ID_ICON2 101#define ID_ICON3 102 在.RC文件中: / here are the icon defines,note the use of C+ commentsID_ICON1 ICON star.icoID_ICON2 ICON ball.icoID_ICON3 IC

17、ON cross.ico 程序代碼可以像下面一樣: / Notice the use of hinstance instead of NULL。/ use the MAKEINTRESOUCE macro to reference/ symbolic constant resoure properlyWinclass.hIcon = LoadIcon(hinstance, MAKEINTRESOUCE(ID_ICON1);Winclass.hIconSm = LoadIcon(hinstance, MAKEINTRESOUCE(ID_ICON1); 注意宏MAKEINTRESOURCE()的使

18、用。該宏將整數(shù)轉(zhuǎn)換為一個字符串指針,但是不必?fù)?dān)心該操作只在使用已經(jīng)#define的符號常數(shù)時應(yīng)用它。使用光標(biāo)資源光標(biāo)資源幾乎和圖標(biāo)資源相同。光標(biāo)文件是一個小位圖,擴展名為.CUR,可以在大多數(shù)IDE編譯器中創(chuàng)建,或者使用單獨的圖像處理程序來創(chuàng)建。光標(biāo)通常是3232以及16位色彩的,最高可達(dá)6464以及256色彩,甚至可以采用動畫。假定已經(jīng)使用IDE或一個單獨的繪圖程序創(chuàng)建了一個光標(biāo)文件,將它們添加到.RC文件中以及通過程序來訪問它們的步驟和圖標(biāo)的情況相似。要定義一個光標(biāo),使用.RC文件中的光標(biāo)關(guān)鍵字。88X 第3章 高級Windows 編程 X 方法I通過字符串名cursor_name CUR

19、SOR FILENAME.CUR例如:windowcursor CURSOR crosshair.curMyCoolCursor CURSOR greenarrow.cur或者是方法II通過整型標(biāo)識符cursor_id CURSOR FILENAME.CUR例如:windowcursor CURSOR bluearrow.cur292 CURSOR redcross.cur當(dāng)然,如果想使用符號標(biāo)識符,必須創(chuàng)建一個.H文件以及符號的定義。 RESOURCES.H的內(nèi)容:#define ID_CURSOR_CROSSHAIR 200 / these mumbers are arbitrary#de

20、fine ID_CURSOR_GREENARROW 201RESOURCES.RC的內(nèi)容:#include “RESOURCES.H”/ here are the icon defines,note the use of C+ commentsID_CURSOR_CROSSHAIR CURSOR crosshair.curID_CURSOR_GREENARROW CURSOR greenarrow.cur 沒有任何原因說明一個資源數(shù)據(jù)文件為什么不能存在于其他目錄中。例如greenarrow.cur可能存在于一個CURSOR目錄的根目錄下,像下面一樣:ID_CURSOR_GREENARROW C

21、URSOR C:CURSORgreenarrow.cur技 巧 我已經(jīng)為本章創(chuàng)建了一些光標(biāo).cur文件。使用你的IDE來瀏覽一下這些光標(biāo)文件,或者僅打開該目錄,Windows將通過其文件名顯示每個光標(biāo)文件的位圖?,F(xiàn)在已經(jīng)了解了如何向一個.RC文件中添加一個光標(biāo)資源,下面是按照字符串名從應(yīng)用程序中加載該資源的程序代碼。 89X 游戲編程大師 X在.RC文件中:CrossHair CURSOR crosshair.cur在程序代碼中:/ 注意使用hinstance而不是NULLWinclass.hCursor = LoadCursor(hinstance, “crossiHair”); 要通過.H

22、文件中定義的符號標(biāo)識符來裝載光標(biāo),具體步驟如下。在.H文件中:#define ID_CROSSHAIR 200在.RC文件中:ID_CROSSHAIR CURSOR crosshair.cur在程序代碼中:/ 注意使用hinstance而不是NULLWinclass.hCursor = LoadCursor(hinstance, MAKEINTRESOURCE(ID_CROSSHAIR);現(xiàn)在已經(jīng)是第二次使用宏MAKEINTRESOURCE()來將符號整型ID轉(zhuǎn)換為Windows系統(tǒng)使用的格式。好,有一個細(xì)節(jié)可能還沒有引起你的注意。到現(xiàn)在為止只遇到了Windows類圖標(biāo)和光標(biāo)。但是在窗口之間操

23、作窗口圖標(biāo)和光標(biāo)可能嗎?例如,如果想創(chuàng)建二個窗口,并且使光標(biāo)在兩個窗口之間不同。要想做到這一點的話,應(yīng)當(dāng)使用SetCursor()函數(shù):HCURSOR SetCursor(HCURSOR hCursor);其中,hCursor是一個由LoadCursor()檢索的光標(biāo)句柄。使用該技術(shù)惟一的問題就是SetCursor()函數(shù)不太靈便,因此應(yīng)用程序中必須在鼠標(biāo)從一個窗口移動到另一個窗口的同時跟蹤和改變光標(biāo)。下面是一個設(shè)置光標(biāo)的例子: / load the cursor somewhere maybe in the WM_CREATEHCURSOR hcrosshair = LoadCursor(h

24、instance, “CrossHair”); / later in program code to change the cursorSetCursor(hcrosshair); CD-ROM上DEMO3_1.CPP給出了一個設(shè)置窗口圖標(biāo)和鼠標(biāo)光標(biāo)的例子。下面清單給出了加載新圖標(biāo)和光標(biāo)的重要的代碼部分的摘錄。 90X 第3章 高級Windows 編程 X/ include resources#include “ DEMO3_1RES.H”./ changes to the window class definitionwinclass.hIcon =LoadIcon(hinstance, M

25、AKEINTRESOURCE(ICON_T3DX);winclass.hCursor=LoadCursor(hinstance, MAKEINTRESOURCE(CURSOR_CROSSHAIR);winclass.hIconSm = LoadIcon(hinstance, MAKEINTRESOURCE(ICON_T3DX); 并且,程序使用了資源腳本程序DEMO3_1.RC和資源頭文件DEMO3_1RES.H。DEMO3_1RES.H的內(nèi)容: #define ICON_T3DX 100#define CURSOR_CROSSHAIR 200 DEMO3_1.RC的內(nèi)容: #include

26、“DEMO3_1RES.H” / note that this file has different types of resourcesICON_T3DX ICON t3dx.icoCURSOR_CROSSHAIR CURSOR crosshair.cur 要自己建立應(yīng)用程序,你需要下面文件: DEMO3_1.CPPC/C+主文件DEMO3_1RES.H定義符號的頭文件DEMO3_1.RC資源腳本程序T3DX.ICO圖標(biāo)的位圖數(shù)據(jù)CROSSHAIR.CUR光標(biāo)的位圖數(shù)據(jù) 所有這些文件都應(yīng)當(dāng)放在同一個目錄下作為一個工程。否則編譯器和連接器很難找到它們。一旦創(chuàng)建并運行了該程序,或者使用預(yù)編譯程序

27、DEMO3_1.EXE,就應(yīng)當(dāng)看到如圖3.5所示的圖像,非常酷,是吧!91X游戲編程大師X圖 3.5關(guān)于常用圖標(biāo)和光標(biāo)的 DEMO3_1.EXE 的輸出結(jié)果作為一個試驗,嘗試用 IDE 打開 DEMO3_1.RC 文件。圖 3.6 表示了我使用 VC+5.0 所 作的內(nèi)容。但是,使用專用編譯器應(yīng)當(dāng)?shù)玫讲煌慕Y(jié)果,因此如果結(jié)果不相同也不必大驚小 怪。OK!在進(jìn)入下面內(nèi)容之前討論一下 IDE。如前所述,可以使用 IDE 來創(chuàng)建.RC 和.H 文 件,但是,應(yīng)當(dāng)閱讀一下 IDE 的手冊。圖 3.6在 VC+5.0 環(huán)境下打開 DEMO3_1.RC 源程序的結(jié)果但是裝載一個人工編寫的.RC 文件還有一

28、個問題,如果使用你的 IDE 保存該文件的話, 毫無疑問 Windows 編譯器認(rèn)為在.RC 文件中造成了無數(shù)的注釋、宏、定義(#define)以及其 他垃圾數(shù)據(jù)。實際上該問題的本質(zhì)是如果想編輯人工編寫的.RC 文件的話,應(yīng)當(dāng)將.RC 文件92 X 第3章 高級Windows 編程 X 作為文本來加載來進(jìn)行編輯。這樣編譯器就不會將它作為一個.RC文件來裝載,但是應(yīng)當(dāng)注意只能是無格式的ASCII文本。創(chuàng)建字符串表格資源如引言中所提到的,Windows支持字符串資源。和其他資源不同的是,只能使用一個字符串表單來容納所有的字符串。并且字符串資源不允許通過字符串來定義。因此,在.RC文件中定義的所有字

29、符串表單必須和符號引用常量以及相關(guān)的解釋該引用的.H頭文件同時使用。我依然不能確認(rèn)我使用字符串資源的感受。使用字符串資源實際上和使用頭文件相同,并且兩種情況下字符串或無格式頭文件都必須重新編譯。因此,我認(rèn)為沒有使用它們的必要。但如果你確實不嫌麻煩,可以將字符串資源放入.DLL文件中,主程序就不必要再重新編譯它們。但是,我是一個技術(shù)人員,不是思想家,誰去關(guān)心這些問題?要在.RC文件中創(chuàng)建一個字符串表單,必須使用下面語法: STRINGTABLEID_STRING1, “string 1”ID_STRING2, “string 2”. 當(dāng)然,符號常量可以是任何東西,就像注釋中的字符串一樣。只有一條

30、原則:每行字符串不能超過255個字符(包括常量本身在內(nèi))。下面是一個包含可能在游戲菜單中使用的字符串表單的.H和.RC文件的例子。.H文件包含有: / 常數(shù)值取決于你#define ID_STRING_START_GAME 16#define ID_STRING_LOAD_GAME 17#define ID_STRING_SAVE_GAME 18#define ID_STRING_OPTIONS 19#define ID_STRING_EXIT 20 .RC文件中含有: / note the stringtable does not have a name since/ only one st

31、ringtable is allowed per .RC fileSTRINGTABLEID_STRING_START_GAME,“Kill Some Aliens”ID_STRING_LOAD_GAME “Doenload Logs”93X 游戲編程大師 XID_STRING_SAVE_GAME “Upload Data”ID_STRING_OPTIONS “Tweak The Settings”ID_STRING_EXIT “Lets Bail!”技 巧 你幾乎可以將所有的想添加的內(nèi)容都放到字符串表單中,包括printf()命令格式如%d、%s等等。不能使用換行符“n”,但是可以使用八進(jìn)制

32、換碼順序如015等等。一旦創(chuàng)建了含有字符串資源的源文件,應(yīng)當(dāng)使用LoadString()函數(shù)來裝載某一個字符串,下面是LoadString()函數(shù)的原型: int LoadString(HINSTANCE hInstance, / handle of module withstring resourceUINT uID, / resource identifierLPTSTR lpBuffer, / address of buffer for resourceint nBufferMax); / size of buffer LoadString()返回一個所讀字符的數(shù)量,或者在調(diào)用不成功時返

33、回0。下面是如何在游戲運行過程中調(diào)用和保存游戲字符串的函數(shù): / create some storage spacechar load_string80, / used to hold load game stringsave_string80, / used to hold sava game string / load in the first string and check for errorif (!LoadString(hinstance, ID_STRING_LOAD_GAME, load_string, 80)/ theres an error /end if / load i

34、n the second string and check for errorif (!LoadString(hinstance, ID_STRING_SAVE_GAME, save_string, 80)/ theres an error /end if / use the strings now 和前面一樣,hinstance是應(yīng)用程序在WinMain()中傳遞的實例。上面已經(jīng)包含了所有的字符串資源的用法。如果你能為它們找到更好的用處,請給我發(fā)一個email:ceo。使用聲音資源到現(xiàn)在為止,或許你已經(jīng)能夠方便地使用資源腳本程序,又或許你已經(jīng)非常厭煩以至于打算攻擊我的Web頁,來對我進(jìn)行破壞

35、了。請記住,那是Microsoft公司 94 X 第3章 高級Windows 編程 X ()開發(fā)的內(nèi)容。我僅僅是了解它而已。好吧,我已經(jīng)向你聲明了不經(jīng)常使用的否認(rèn)聲明,讓我們繼續(xù)下面的裝載聲音資源的內(nèi)容!大多數(shù)游戲都是用兩種聲音類型中的一種: 數(shù)字化 .WAV文件 MIDI .MID文件據(jù)我所知,Windows的標(biāo)準(zhǔn)資源僅支持.WAV文件,因此我就只分析如何創(chuàng)建.WAV資源。當(dāng)然如果不支持.MID資源的話,你可能只能創(chuàng)建用戶定義的資源類型。我們現(xiàn)在不討論這個主題,但別處會加以討論。所需要的第一個事情就是一個.WAV文件,它只是一個含有大量的8位或16位的一定頻率脈沖的數(shù)字式數(shù)據(jù)波形。對于游戲聲

36、音效果來講,典型的脈沖頻率為11MHz、22 MHz和44 MHz(CD級品質(zhì))。該內(nèi)容仍然和你無關(guān),但我希望對該內(nèi)容概述一下。在我們學(xué)習(xí)DirectSound時,將會學(xué)習(xí)有關(guān)數(shù)字采樣理論和.WAV文件的全部內(nèi)容?,F(xiàn)在,只討論一下樣本大小和頻率。我們假設(shè)你的磁盤上已經(jīng)有了.WAV文件,并且希望將該文件添加到一個源文件中,能夠裝載并且按照一定的程序播放。Lets go on!.WAV文件的源類型就是WAVE這是令人驚奇的事。要將該文件添加到.RC文件中,應(yīng)當(dāng)使用下面語法:方法I通過字符串名wave_name WAVE FILENAME.WAV例如:BigExplosion WAVE expl1.

37、wavrFireWeapons WAVE fire.wav 方法II通過整型標(biāo)識符ID_WAVE CURSOR FILENAME.CUR例如:DEATH_SOUND_ID WAVE die.wav20 WAVE intro.wav 當(dāng)然,該符號常量應(yīng)當(dāng)在一個.H文件中的某處進(jìn)行定義,這部分內(nèi)容我們已經(jīng)有所了解。對于這一點,我們可能碰上了一個小障礙:WAVE資源要比光標(biāo)、圖表和字符串表單要復(fù)雜一點。所以問題是裝載聲音資源的程序要比裝載其他資源要復(fù)雜一些,因此我們現(xiàn)在就不介紹在一個實際游戲中裝載.WAV資源的方式,在后面再詳細(xì)介紹。現(xiàn)在介紹一下使用95X 游戲編程大師 XPlaySound()函數(shù)

38、裝載和播放.WAV文件的技巧。下面是PlaySound()函數(shù)的原型: BOOL PlaySound(LPCSTR pszSound, / string of sound to playHMODULE hmod, / instance of applicationDWORD fdwSound); / flags parameter 和LoadString()不同的是,PlaySound()稍微有點復(fù)雜,因此我們要深入了解一下每一個參數(shù): PszSound該參數(shù)或者是資源文件中聲音資源的字符串名,或者是磁盤上的文件名。并且可以使用MAKEINTRESOURCE()并且應(yīng)用使用符號常量定義的一個W

39、AVE。 Hmod裝載該資源的應(yīng)用程序?qū)嵗?。它只是一個應(yīng)用程序?qū)嵗?FdwSound這是個關(guān)鍵參數(shù)。該參數(shù)控制聲音如何裝載和播放。表3.1列出了FdwSound的一些最有用的值。表3.1 PlaySound()函數(shù)的FdwSound參數(shù)的值 值SND_FILENAMESND_RESOURCESND_MEMORYSND_SYNCSND_ASY NC 描 述 該PszSound參數(shù)是文件名 該PszSound參數(shù)是一個資源標(biāo)識符;hmod必須辨別包含該資源的實例 裝載到RAM中的聲音事件文件。FdwSound參數(shù)指定的該參數(shù)必須指向內(nèi)存中的聲音文件的圖像 聲音事件的同步反饋。聲音事件播放完畢后,

40、PlaySound()返回。 聲音事件的異步播放,開始播放聲音后,PlaySound()立即返回。要終止異步播放的波形聲音,調(diào)用PlaySound(),并且PszSound設(shè)為NULL聲音重復(fù)播放直到再次調(diào)用PlaySound(),并且PszSound設(shè)為NULL,并且需要指定SND_ASYNC標(biāo)識符來制定一個異步聲音事件不使用默認(rèn)聲音事件。如果沒有發(fā)現(xiàn)聲音文件,PlaySound()返回靜音而不播放默認(rèn)聲音因為調(diào)用任務(wù)而終止聲音。如果PszSound不為NULL的話,將停止所有指定聲音的事件。如果PszSound為NULL的話,將停止所有代表調(diào)用任務(wù)的聲音指定聲音事件將讓位于另外一個已經(jīng)播放

41、的聲音事件。如果一個聲音由于產(chǎn)生該聲音所需要的資源正在播放其他聲音文件而不能播放當(dāng)前聲音,該函數(shù)不播放所要求的聲音,而是立即返回錯誤如果驅(qū)動器正忙,不播放聲音,該函數(shù)就立即返回 SND_LOOP SND_NODEFAULT SND_PURGE SND_NOSTOP SND_NOWAIT要使用PlaySound()播放一個WAVE聲音資源,一般需要下面四個步驟:96X 第3章 高級Windows 編程 X1. 創(chuàng)建.WAV文件并存儲在磁盤上。2. 創(chuàng)建.RC資源腳本程序以及相關(guān)的頭文件。3. 編譯該資源和程序代碼。4. 使用MAKEINTRESOURCE()宏,通過WAVE資源名或者是通過WAV

42、E資源標(biāo)識符在程序中設(shè)定一個PlaySound()的調(diào)用。讓我們看幾個例子。首先是有兩種聲音的常規(guī)RC文件:一個是字符串名的聲音文件,另一個符號常量的聲音文件,分別命名為RESOURCE.RC和RESOURCE.H。該文件如下:RESOURCE.H文件包含:#define SOUND_ID_ENERGIZE 1RESOURCE.RC文件包含:# include “ RESOURCE.H” / first the string name defind sound resourceTelporter WAVE teleport.wav / and now the symbolically defi

43、ned soundSOUND_ID_ENERGIZE WAVE energize.wav 在程序中,下面顯示了如何以不同方式播放聲音: / to play the telport sound asynchronouslyPlaySound(“Teleporter”, hinstance,SND_ASYNC | SND_RESOURCE); / to play the telport sound asynchronously with loopingPlaySound(“Teleporter”, hinstance,SND_ASYNC | SND_LOOP | SND_RESOURCE); /

44、to play the energize sound asynchronouslyPlaySound(MAKEINTRESOURCE(SOUND_ID_ENERGIZE), hinstanceSND_ASYNC | SND_RESOURCE); / and if you simply wanted to sound off disk/ directly then you could do thisPlaySound(“C:pathfilename.wav”, hinstance,SND_ASYNC | SND_FILENAME); 要停止所有的聲音,使用SND_PURGE標(biāo)識符并將聲音名設(shè)為N

45、ULL,如下所示:/ stop all soundsPlaySound(NULL, hinstance, SND_PURGE); 很明顯,有許多標(biāo)識符選項可以自由選擇匹配。但是仍然沒有任何控制或菜單,所以很難對演示應(yīng)用程序產(chǎn)生影響。作為一個簡單的使用聲音資源的演示程序來講,我已經(jīng)創(chuàng)建了DEMO3_2.CPP,可以從磁盤上找到。下面就將該程序列出清單,但是99%的程序都是曾經(jīng)97X 游戲編程大師 X使用過的標(biāo)準(zhǔn)的模板,而聲音代碼也和前面例子中的代碼行基本相同。該演示程序是預(yù)編譯的程序,可以運行DEMO3_2.EXE來瀏覽。但是我還是想列出所使用的.RC文件和.H文件,分別是DEMO3_2.RC和

46、DEMO3_2RES.H文件:DEMO3_2RES.H文件內(nèi)容: / defines for sound ids#define SOUND_ID_CREATE 1#define SOUND_ID_MUSIC 2 / defines for icons#define ICON_T3DX 500 / defines for cursors#define CURSOR_CROSSHAIR 600 DEMO3_2.RC文件內(nèi)容: #include “DEMO3_2RES.H” / the sound resourcesSOUND_ID_CREATE WAVE create.wavSOUND_ID_MU

47、SIC WAVE techno.wav / icon resourcesICON_T3DX ICON T3DX.ICO / cursor resourcesCURSOR_CROSSHAIR CURSOR CROSSHAIR.CUR 可以看到我在代碼中也包含了圖標(biāo)和光標(biāo)資源,從而使程序更具趣味性。要編制DEMO3_2.CPP,我采用了標(biāo)準(zhǔn)Windows演示程序,并且在兩部分內(nèi)容中添加了聲音代碼的調(diào)用:WM_CREATE消息和WM_DESTROY消息。在WM_CREATE消息處,設(shè)置了兩個聲音效果,一個聲音在說:“創(chuàng)建窗口(Creating window)”,然后停止;另一個是以循環(huán)模式播放的一小

48、段音樂,能夠一直播放下去。在WM_DESTROY消息部分停止所有的聲音。 注 意 第一段聲音,我使用SND_SYNC標(biāo)志。使用該標(biāo)志是因為PlaySound()一次只允許播放一個聲音,而且在播放過程中,我不希望第二段聲音終止第一段聲音。下面是從DEMO3_2.CPP文件中添加到WM_CREATE消息和WM_DESTROY消息中的代碼:case WM_CREATE:98X 第3章 高級Windows 編程 X/ do initialization stuff here / play the create sound oncePlaySound(MAKEINTRESOURCE(SOUND_ID_C

49、REATE),hinstance_app,SND_RESOURCE | SND_SYNC); / play the music in loop modePlaySound(MAKEINTRESOURCE(SOUND_ID_MUSIC),hinstance_app,SND_ RESOURCE | SND_ASYNC | SND_LOOP); / return successreturn(0); break; case WM_DESTROY:/ stop the sounds firstPlaySound(NULL, hinstance_app, SND_PURGE); / kill the ap

50、plication,this sends a WM_QUIT messagePostQuitMessage(0); / return successreturn(0); break; 從上面代碼中,可以發(fā)現(xiàn)有一個變量hinstance_app,用來作為PlaySound()調(diào)用的應(yīng)用程序?qū)嵗浔?。這只是一個全局變量,用來保存WinMain()中傳遞的實例。它的代碼緊跟在WinMain()中類定義的后面,如下所示: ./ 在全局變量中保存實例hinstance_app = hinstance; / 注冊該窗口類if (!RegisterClassEx(&winclass)return(0);.

51、要建立該應(yīng)用程序,在工程中需要包含下列文件:DEMO3_2.CPP源文件主程序。DEMO3_2RES.H包含所有符號的頭文件。99X游戲編程大師XDEMO3_2.RC 源文件腳本程序。 TECHNO.WAV 音樂片斷,需要放在工作目錄下。 CREATE.WAV 創(chuàng)建窗口聲音,需要放在工作目錄下。 WINMM.LIB Windows 多媒體庫擴展。該文件位于編譯器的 LIB目錄下。應(yīng)當(dāng)將該 文件添加到從該目錄到輸出的所有工程中。 MMSYSTEM.H WINMM.LIB 的頭文件, 該文件已被包含在 DEMO3_2.CPP 和我的所 有演示程序中。你所應(yīng)了解的就是該文件應(yīng)當(dāng)位于你的編譯器搜索路徑

52、中。它也是標(biāo)準(zhǔn) Win32 頭文件集中的一部分。使用編輯器創(chuàng)建 文件創(chuàng)建 Windows 應(yīng)用程序的大多數(shù)編譯器都需要一個相當(dāng)大的開發(fā)環(huán)境,如 Windows 的 Visual Development Studio 等。每一個 IDE 都含有一個或多個使用即插即用技術(shù)的自動創(chuàng)建 不同資源、資源腳本程序和相關(guān)頭文件的工具。 使用這些工具的惟一問題是要學(xué)習(xí)這些工具!并且,使用 IDE 創(chuàng)建的.RC 文件都是人工 可讀寫的 ASCII 碼文本, 但是又有大量的添加的定義 (#define) 和宏, 編譯器能夠添加它們, 以便于自動完成并且簡化常量的選擇和 MFC 界面工作。 因為現(xiàn)在我是 Micro

53、soft VC+5.0 用戶,我簡要說明一下關(guān)于使用 VC+5.0 資源處理支 持的關(guān)鍵要素。首先,向工程中添加資源可以有兩種方式: 方法 I從主菜單中使用 File、New 選項,可以向工程中添加大量的資源。圖 3.7 就是 進(jìn)行該操作后產(chǎn)生的對話框屏幕圖。當(dāng)添加圖標(biāo)、光標(biāo)、位圖等資源時, IDE 編譯器自動 生成 Image Editor(如前面圖 3.4 所示) 。這是一個原始的圖像編輯單元,可以用來繪制光標(biāo) 和圖標(biāo)。如果要添加一個菜單資源(該部分內(nèi)容將在下面部分討論) ,就會出現(xiàn)菜單編輯器。圖 3.7使用 VC+5.0 中的文件、新建來添加資源方法 II 該方法更靈活一點,含有所有可能

54、的資源類型,而方法 I 只支持其中的一部100 X第 3 章 高級 Windows 編程X分。要向工程中添加任何一種類型的資源,可以使用主菜單中的 Insert、Resource 選項。圖 3.8 表示了顯示出的對話框。在這種情況下,你還需要進(jìn)行一些維護(hù)(手工進(jìn)行編輯) 。無論 何時想添加一個資源,都必須將它添加到資源腳本程序中 對嗎?因此,如果你的工程中 還沒有一個資源腳本程序的話, 編譯器 IDE 將為你產(chǎn)生一個腳本程序, 稱之為 SCRIPT*.RC。 另外,這兩種方法最終都將生成一個名為 RESOURCE.H 的文件。該文件含有使用編輯器定 義的和資源有關(guān)的資源符號、標(biāo)識符值等。圖 3

55、.8使用插入資源來向應(yīng)用程序中添加資源我當(dāng)然希望深入探討有關(guān)使用 IDE 進(jìn)行資源編輯的內(nèi)容, 但由于它只是整章內(nèi)容的一部 分,而不是一整本書,所以請你自己閱讀一下關(guān)于使用編譯器進(jìn)行文檔編制的內(nèi)容。本書中 我們將不會使用更多的資源,因此上述討論的信息已經(jīng)足夠了。下面讓我們進(jìn)行更復(fù)雜的資 源類型 菜單的學(xué)習(xí)吧。使用菜單編程菜單是 Windows 程序中最酷的一個內(nèi)容,可以說是人機交互式界面的關(guān)鍵所在(例如 制造一個文字處理器) 。了解如何創(chuàng)建和使用菜單是非常重要的,這是因為你可能想制作簡 單的工具來幫助創(chuàng)建游戲,或者是想有一個視窗基礎(chǔ)的前端來作為游戲的開始。而這些工具 毋庸置疑地要有大量的菜單(

56、如果要制作一個 3D 工具的話,可能需要上百萬個菜單) 。請 相信我!無論是哪種情況,都必須掌握如何創(chuàng)建、裝載和響應(yīng)菜單。創(chuàng)建一個菜單使用編譯器的菜單編輯器可以創(chuàng)建一個完整的菜單以及相關(guān)的文件, 但是現(xiàn)在我們?nèi)斯?編寫它,因為我不知道你在使用哪種編譯器,這樣你也可以學(xué)會菜單說明書中的內(nèi)容。但是 當(dāng)你正在編寫一個實際的應(yīng)用程序創(chuàng)建一個菜單時,大多數(shù)是應(yīng)用 IDE 編輯器來創(chuàng)建菜單, 因為人工輸入編寫菜單實在是太復(fù)雜了。它就像 HTML 代碼 當(dāng)啟動 Web 后,使用一個 文本編輯器來制作一個主頁并不是一件很復(fù)雜的事。但是,不使用任何工具來創(chuàng)建 Web 站101 X 游戲編程大師 X點幾乎是不可能

57、的?,F(xiàn)在,就讓我們開始制作菜單!實際上菜單和已經(jīng)討論過的其他資源完全一樣。它們駐留在一個.RC資源腳本程序中,并且必須擁有一個.H文件來解決符號引用問題,符號引用是所有菜單的標(biāo)識符(一個例外:菜單名必須是符號的,無名稱字符串)。下面是在.RC文件中常見的一個菜單說明的基本語法: MENU_NAME MENU DISCARDABLE / you can use BEGIN instead of if you wish / menu definitions / you can use END instead of if you wish MENU_NAME可以是一個名稱字符串或這是一個符號,關(guān)鍵字

58、DISCARDABLE是不完整的但又是必須的??瓷先シ浅:唵?,當(dāng)然,中間內(nèi)容省略了,我會在后面討論!在編寫定義菜單項和子菜單的代碼之前,我們首先了解一些直觀的相關(guān)術(shù)語。上述討論可以參見圖3.9中菜單,它有兩個一級菜單:File和Help。File菜單中包含四個菜單項:Open、Close、Save和Exit。幫助菜單中只有一個菜單項:About。因此說本菜單中含有一級菜單和菜單項。但是,這容易令人造成誤解,因為菜單中還可能有菜單或者是層疊式菜單。我不準(zhǔn)備創(chuàng)建層疊式菜單,但是層疊式菜單的原理很簡單:使用一個菜單定義來定義一個菜單項本身,并且可以循環(huán)無休止的這樣做下去。菜單欄 圖3.9 有兩個子菜

59、單的菜單欄現(xiàn)在我們了解了相關(guān)術(shù)語,下面是執(zhí)行圖3.9所示的菜單: MainMenu MENU DISCARDABLEPOPUP “File”MENUITEM “Open”, MENU_FILE_ID_OPENMENUITEM “Close”, MENU_FILE_ID_CLOSEMENUITEM “Save”, MENU_FILE_ID_SAVEMENUITEM “Exit”, MENU_FILE_ID_EXIT / end popup102 X 第3章 高級Windows 編程 XPOPUP “Help”MENUITEM “About”, MENU_HELP_ABOUT / end popu

60、p / end top level menu 我們來逐段分析該菜單定義。首先該菜單名為MainMenu。對于這一點,我們并不知道它是一個名稱字符串,還是一個標(biāo)識符,但是因為我一般都大寫所有常量的第一個字母,很清楚它是一個無格式字符串。這也正是我要做的內(nèi)容。向下看,有兩個一級菜單定義,都以關(guān)鍵字POPUP開頭這就是關(guān)鍵所在。POPUP指出了一個菜單可以使用下面ASCII名稱和菜單項來定義。ASCII名必須跟在關(guān)鍵字POPUP后面,并且用括號來包起來。彈出式菜單定義必須放在 或BEGIN END塊中喜歡使用哪種都可以。(使用Pascal語言的人應(yīng)當(dāng)高興了)。在該定義塊中,后面是所有的菜單項。要定義

溫馨提示

  • 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)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論