送給初學者的禮物:C++游戲編程起源連載二

字號:

第二章 使用Win32程序資源
    一、簡介
    歡迎繼續(xù)收看!通過本章題目可能你已經(jīng)猜出了本章論題,我將教會你在Windows程序中使用資源。簡單的講,資源即數(shù)據(jù),它們通常是和程序的EXE文件相關(guān)聯(lián)的,但是它們又是獨一無二的。首先,資源在運行過程中不能被修改。它們實際上都是只讀文件,而且程序代碼不能夠直接訪問它們。另外,資源并不在程序的數(shù)據(jù)區(qū)內(nèi)。在裝入時,程序資源通常在某個磁盤文件中,直到程序需要它們時才被裝入。使用資源是一件很容易的事情,并且它的妙處無窮。Windows為我們提供了大量的資源類型,但我們這里只學一些最常用,最容易的:圖標(icon)、光標(cursor)、位圖(bitmap)、菜單(menu)和字符串(string)。此后,我還將教你建立自己風格類型的資源,使你為所欲為。
    重復一下,要想看懂本章,你得有點C語言的基礎(chǔ)。C++有時用一用,但不影響你學習本章內(nèi)容。并且我假定你已經(jīng)讀過了上一章內(nèi)容“Windows編程基礎(chǔ)”。還是用Microsoft Visual C++的編譯器。
    資源腳本
    在進行細節(jié)之前,我們要先搞懂怎樣要編譯器知道它所要編譯的資源類型。方法是使用稱之為資源腳本的特殊文件,它是一個簡單的文本文件,可以手工編輯,也可以讓Visual C++自動編輯,或者你用其它的自動編輯器編輯。無論如何,資源腳本文件要有一個.rc的擴展名。大多數(shù)的腳本文件都從定義資源行開始,最簡單的資源行通常要用到資源類型,就像這樣:
    [identifier] [resource type] [filename]
     【標識符】 【資源類型】 【文件名稱】
    標識符可以用兩種方式表示:一種是能表示資源意思的字符串,另一種是在資源相對應的頭文件中用#define定義過的數(shù)字常量。如果你選擇數(shù)字常量,這通常是一個好主意,別忘了把相應的頭文件加入到你的資源腳本。資源腳本使用C語言風格的文件格式好像比較容易理解。以下是一個比較簡單的資源腳本實例:
    #include "resource.h"
    // icons
    ICON_MAIN ICON myicon.ico
    // bitmaps
    IMG_TILESET1 BITMAP tileset.bmp
    IMG_TILESET2 BITMAP tileset2.bmp
    例子中的ICON_MAIN和IMG_TILESET是字符串呢,還是數(shù)字常量?這無傷大雅,編譯器編譯的時候會自己判斷。如果發(fā)現(xiàn)在頭文件中有#define的定義,那就認為是字符常量,否則,就是字符串。如果有些迷茫,不要緊。我將解釋我們要用到的每一個資源類型。如果您覺得麻煩那讓我們用全自動的資源插入系統(tǒng)吧?。ㄔ赩isual C++中,在“插入”下拉菜單中,選擇“資源”)現(xiàn)在你知道了建立資源腳本的基礎(chǔ)知識,讓我們開始進一步的行程吧!
    圖標和光標
    你每天在使用的大多數(shù)的Windows程序,都有自己的圖標,簡單的說,就是EXE文件同這個圖標資源相關(guān)聯(lián)了,獨特風格的光標也是如此。你已經(jīng)知道圖標的腳本行樣子了,光標的和它很相似,看看吧:
    [identifier] CURSOR [filename]
    [identifier] ICON [filename]
    增加了一行腳本行后,也就是意味著你的EXE文件又多了一個關(guān)聯(lián)。也就是說你的EXE文件要根據(jù)標識符去相應的位置尋找相應的文件[filename]。你可以使用任何你喜歡用的圖標/光標編輯器去編輯相應的文件。我通常利用Visual C++中的編輯器。
    把資源腳本做出來后,并沒有完事兒,因為你還不知道怎么調(diào)用相應的資源,要想知道圖標和光標是怎樣在你的程序中被調(diào)用的,讓我們回過頭來,看一看上一章中的窗口類(windows class)文件:
    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;
    // message handler function
    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
    還記得它吧?這個hIcon用來表示整個程序;hIconSm用來出現(xiàn)在開始菜單和窗口的標題欄里;hCursor用來表示在你所創(chuàng)建的窗口中的光標的樣子。我向你保證,我們要實現(xiàn)自己的風格一點都不復雜。下面是它們的原形:
    HICON LoadIcon(
     HINSTANCE hInstance,
    // handle to application instance
     LPCTSTR lpIconName
    // icon-name string or icon resource identifier
    );
    HCURSOR LoadCursor(
     HINSTANCE hInstance,
    // handle to application instance
     LPCTSTR lpCursorName
    // name string or cursor resource identifier
    );