[翻譯]-Windows CE 程式設計 (3rd 版)–4.5 資源

來源:互聯網
上載者:User

翻譯 tellmenow

資源
資源是應用程式或DLL的一個唯讀資料區段,在模組被編譯後,資源被連結到模組中。資源為開發人員提供了一個與編譯器無關的位置,用來儲存常量資料,例如對話方塊、字串、位元影像、表徵圖以及菜單。因為資源並不編譯在程式裡,所以改變它們並不用重新編譯器。

您可以通過構造一個描述資源的的ASCII檔案--資源指令碼--來建立資源。ASCII檔案的副檔名叫RC。您可以用資源編譯器來編譯該檔案,每個Windows開發工具的製造者都提供該編譯器。隨後您可以用連結器把該檔案連結到編譯後的可執行檔中。現在,這些步驟被厚厚的可視工具層掩蓋了,但功能依然保持相同。例如,即使很少還有程式員會直接看資源檔,但eVC++依然建立和維護一個ASCII資源檔(RC)。

對編程書籍的作者來說,決定如何選擇工具是一件很痛苦的事情。一些工具側重於進階指令,談論菜單選擇,描述對話方塊。另一些則使用ASCII檔案和命令列編譯器,為讀者展示如何從頭開始構建程式的所有組件。我可以描述如何使用視覺化檢視或者如何為資源建立基本的ASCII檔案。在本書中,我著重在ASCII資源指令碼層級,因為目標是講授Windows CE編程,而不是如何使用特殊的工具集。我還將示範如何通過建立和使用ASCII RC檔案來增加菜單等。但在本書後面與資源檔不相關的地方,我不會總是將RC檔案包含在清單裡的。當然,這些檔案會包含在附書的CD裡。

資源指令碼
建立資源指令碼同使用記事本建立一個文字檔一樣容易。使用的語言簡單,有些像C語言。使用//來標記注釋行,使用#include來包含檔案。

菜單模板樣本如下:
//
// A menu template
//
ID_MENU MENU DISCARDABLE
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "&Open...",                    100
        MENUITEM "&Save...",                    101
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       120
    END
    POPUP "&Help"
    BEGIN
        MENUITEM "&About",                      200
    END
END

開頭的ID_MENU是資源的ID值。作為可替代的方式,該ID值可以用字串來標記資源。用ID的方式可以提供更緊湊的代碼,而使用字串方式則可以在應用程式從源檔案裡裝載資源的時候提供更好的可讀性。接下來的關鍵字MENU則標記了資源的類型。菜單用POPUP作為開始,指出該功能表項目File實際上是一個綁定到主菜單的彈出式串聯功能表。因為式菜單裡的菜單,所以它也使用BEGIN和END關鍵字來包圍對File菜單的描述資訊。字元&告訴Windows下一個字元是功能表項目的鍵盤快捷符。在功能表項目被顯示的時候,其後的字元會被Windows自動加底線。當使用者按下Alt鍵和該字元,功能表項目會被選擇。菜單裡的每一項被關鍵字MENUITEM標記,後面跟隨的是用在菜單中的字串。在Open和Save字串後的省略符號是Windows 介面習慣,用來告訴使用者選擇該項會顯示一個對話方塊。Open, Save, Exit和About功能表項目後的數字是菜單ID值。這些值用在WM_COMMAND訊息中來標記功能表項目。用定義在通用包含檔案裡的值替代這些值,使它們和WM_COMMAND處理代碼中的值一致,這是一個好的編程習慣。

表4-2列出了您可以在資源檔中找到其它資源類型。DISCARDABLE關鍵字是可選的,用來告訴Windows如果沒有足夠的記憶體時,這些資源可以從記憶體中丟棄。剩下的是BEGIN和END關鍵字,使用括弧{}也是可以的。

表4-2:資源編譯器支援的資源類型

Resource Type

Explanation

MENU

Defines a menu

ACCELERATORS

Defines a keyboard accelerator table

DIALOG

Defines a dialog box template

BITMAP

Includes a bitmap file as a resource

ICON

Includes an icon file as a resource

FONT

Includes a font file as a resource

RCDATA

Defines application-defined binary data block

STRINGTABLE

Defines a list of strings

VERSIONINFO

Includes file version information

[*]The SHMENUBAR resource type used by the Pocket PC is actually defined as RCDATA inside a wizardgenerated include file.

表徵圖
既然我們在使用資源檔,那麼修改Windows CE Shell用來顯示程式的表徵圖就是一件很容易的事情。使用您喜歡的表徵圖編輯器建立表徵圖,並用以下語句加到資源檔:ID_ICON "iconname.ico"。
當在Windows Explorer中顯示程式的時候,Windows在EXE檔案中尋找,從資源清單中找到第一個表徵圖來代表該程式。

讓表徵圖代表應用程式的視窗可能略微有些煩瑣。Windows CE用工具條上一個小的16*16像素的表徵圖代表左面上的視窗。在案頭版的Windows裡,可以用RegisterClassEx函數將小表徵圖和視窗綁定到一起,但在Windows CE裡不支援該函數。作為替代,表徵圖必須顯式裝載和分配給視窗。下面的程式碼片段為視窗指派了一個小表徵圖。

 hIcon = (HICON) SendMessage (hWnd, WM_GETICON, FALSE, 0);
    if (hIcon == 0) {
        hIcon = LoadImage (hInst, MAKEINTRESOURCE (ID_ICON1), IMAGE_ICON, 16, 16, 0);
        SendMessage (hWnd, WM_SETICON, FALSE, (LPARAM)hIcon);
    }

第一個SendMessage調用是用來擷取視窗當前分配的表徵圖。wParam中的FALSE值指出要查詢時段的小表徵圖。如果返回0,表示沒有表徵圖分配過,就調用LoadImage函數從應用程式資源中裝載一個表徵圖。LoadImage函數可以用文本字串或者ID值來標記要裝載的資源。在當前情況下,MAKEINTRESOURCE宏用來為函數產生一個ID值。在Windows CE中,被裝載的表徵圖必須是16*16的表徵圖。LoadImage不會把表徵圖調整到要求的尺寸。在Windows CE下,LoadImage只限於從資源中裝載表徵圖和位元影像。Windows CE另外提供了SHLoadDIBitmap函數用於從檔案中裝載位元影像。

不同於其它版本的Windows,Windows CE將視窗表徵圖儲存在一個基礎類裡。所以如果在一個應用程式裡的兩個視窗具有同樣的類,它們將使用相同的視窗表徵圖。這裡有一個忠告:視窗類別是針對應用程式特定執行個體的。如果您有應用程式FOOBAR的兩個不同執行個體,它們有不同的視窗類別,所以它們可能有不同的視窗表徵圖,即使它們使用相同的類資訊進行的註冊。如果FOOBAR的第二個執行個體有兩個同類的視窗被開啟,這兩個視窗會使用同樣的表徵圖,同FOOBAR第一個執行個體中的視窗表徵圖無關。

加速鍵
可以裝載的另一種資源是鍵盤加速鍵表。通過使用該表,Windows允許開發人員為應用程式中的特定菜單或控鍵指定快速鍵。具體來說,鍵組合用來產生髮送到視窗的WM_COMMAND訊息,而加速鍵就是為鍵組合提供了一個直接的方法。這些加速鍵不同於那些用來訪問File菜單的類似Alt-F的鍵組合。只要File功能表項目字串中使用"&"字元,例如"&File",File菜單鍵組合就會被自動處理。雖然通常鍵盤加速鍵被用來類比菜單操作,例如使用Ctrl-o來開啟一個檔案,但鍵盤加速鍵是獨立於菜單或者其它控制項的。

下面是一個簡短的資源指令碼,定義了一對加速鍵。
ID_ACCEL ACCELERATORS DISCARDABLE
BEGIN
    "N", IDM_NEWGAME, VIRTKEY, CONTROL
    "Z", IDM_UNDO,  VIRTKEY, CONTROL
END

和菜單資源一樣,該結構以一個ID值做為開始。該ID值後面是資源的類型,隨後是可選的discardable關鍵字。加速鍵表的入口項包含標記加速鍵的字母,其後是命令ID值,VIRTKEY表示字母實際上是虛擬索引值,CONTROL關鍵字表示需要Ctrl鍵與加速鍵一起按。

只是在資源檔中有加速鍵表還遠遠不夠。應用程式必須裝載加速鍵表。對從訊息佇列中取出的每個訊息,應用程式還要檢查是否有鍵入了加速鍵。幸運地是,通過簡單修改主訊息迴圈就可以完成這些。下面是一個修改後的處理鍵盤加速鍵的主訊息迴圈。

// Load accelerator table.
hAccel = LoadAccelerators (hInst, MAKEINTRESOURCE (ID_ACCEL));
  
// Application message loop
while (GetMessage (&msg, NULL, 0, 0)) {
    // Translate accelerators
    if (!TranslateAccelerator (hwndMain, hAccel, &msg)) {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }
}

主訊息迴圈中的第一個不同點是使用LoadAccelerators函數裝載加速鍵表。之後,每個訊息從訊息佇列中取出後,都調用TranslateAccelerator。如果該函數轉換了訊息,傳回值是TRUE,這將跳過標準的TranslateMessage和DispatchMessage迴圈體。如果沒有轉換,迴圈體就正常執行。

位元影像也可以被儲存為資源。Windows CE中使用位元影像資源會略微不同於Windows的其它版本。在Windows CE裡,調用LoadBitmap來裝載位元影像的唯讀版本。這意味著當位元影像被選擇進裝置環境變數後,該圖象就不能被這個DC裡的其它繪製操作所修改。該函數原型如下:

BITMAP LoadBitmap(HINSTANCE hInstance, LPCTSTR lpBitmapName);
要裝載一個位元影像資源的可讀寫版,可以使用LoadImage函數。

字串
使用字串資源,將和語言相關的資訊放到編譯的代碼之外,是一種減少應用程式記憶體使用量的好方法。應用程式可以調用int LoadString(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax)來從資源中裝載字串。uID是字串資源的ID,lpBuffer指向接收字串的緩衝區,nBufferMax是緩衝區的大小。在Windows CE裡,為了節省記憶體,LoadString有一個新特性。如果lpBuffer是NULL,LoadString返回一個指向字串的唯讀指標作為傳回值。可以簡單地把傳回值轉換成一個指標,並在需要的時候使用該字串。字串的長度位於字串起始位置之前的一個字裡。需要注意的是,預設情況下,資源編譯器從字串資源中去除結尾的0。如果您想直接讀取字串資源,並讓它們以0做終結符,那麼您可以使用-r命令列開關來啟用資源編譯器。雖然我將在第七章涉及為了節約記憶體而採取的記憶體管理和策略,但是這裡還是有個快速提醒:從資源檔中裝載許多字串到記憶體裡並不是一個好的方法。這將使用資源和RAM裡的記憶體。如果您同時需要很多字串,使用LoadString的新特性返回一個直接指向資源自身的指標會是一個比較好的策略。作為替換,您可以用編譯到程式唯讀段裡的字串。您失去了單獨字串表的優勢,但您減少了記憶體使用量量。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.