第三十二篇:在SOUI2.0中像android一樣使用資源


SOUI2.0之前,在SOUI中使用資源通常是直接使用這個資源的name(一個字符串)來引用。使用字符串的好處在於字符串能夠表達這個資源的意義,因此使用字符串也是現代UI引擎常用的方式。

盡管直接使用字符串有意義明確的優點,它同樣也有缺點:

1、字符串寫錯了,編譯器不知道。這可能導致一些很難發現的BUG。

2、控件查詢,比較時基於字符串,相對來說性能會差一點(好在現在CPU夠強,這點性能損失通常可以忽略)。

做過Android開發的朋友可能知道,在Android中要引用一個資源如圖片、字符串、顏色等可以使用R.id.xxx, R.string.xxx,R.color.xxx這樣的形式來引用。

Android內部全部自動轉換成ID,整數比較顯然比字符串比較快,這里不作討論。

這種方式一個好處在於Android的自動補全功能能夠幫助你快速的輸入你需要的資源,除了加快了編碼速度,還大大減少了輸入錯誤。

SOUI2.0把Android的這種資源引用方式引入了進來。

關鍵在於uiresbuilder。原來SOUI中的uiresbuilder只提供將資源轉換成.rc2功能,方便將資源編譯到EXE/DLL中。

2.0版本新增加name提取,id生成,字符串表ID生成,顏色表ID生成功能。它們會輸出到一個C++頭文件(由命令行參數指定)。

要使用該功能首先要保證所有的布局XML所在的資源類型為"Layout",然后在uiresbuilder的命名行中加入: -h “輸出文件名” idtable。-h 后面緊跟輸出文件名,idtable指示需要給沒有指定ID的控件自動生成ID,該功能默認關閉。

生成成功后,你的“輸出文件”的內容可能是下面的樣子:

//stamp:0ae7b68801b8deb8
/*<------------------------------------------------------------------------------------------------->*/
/*該文件由uiresbuilder生成,請不要手動修改*/
/*<------------------------------------------------------------------------------------------------->*/
#pragma once
#include <res.mgr/snamedvalue.h>
namespace SOUI
{
    const SNamedID::NAMEDVALUE namedXmlID[]={
        {L"btnSelectGif",65540},
        {L"btn_display",65541},
        {L"btn_hidetst",65542},
        {L"btn_lrc",65543},
        {L"btn_menu",65536},
        {L"ctrl_flash",65538},
        {L"gif_test",1000},
        {L"giftest",65539},
        {L"tab_main",65537}        };
    class _R{
    public:
        class _name{
        public:
        _name(){
            btnSelectGif = namedXmlID[0].strName;
            btn_display = namedXmlID[1].strName;
            btn_hidetst = namedXmlID[2].strName;
            btn_lrc = namedXmlID[3].strName;
            btn_menu = namedXmlID[4].strName;
            ctrl_flash = namedXmlID[5].strName;
            gif_test = namedXmlID[6].strName;
            giftest = namedXmlID[7].strName;
            tab_main = namedXmlID[8].strName;
        }
         const wchar_t * btnSelectGif;
         const wchar_t * btn_display;
         const wchar_t * btn_hidetst;
         const wchar_t * btn_lrc;
         const wchar_t * btn_menu;
         const wchar_t * ctrl_flash;
         const wchar_t * gif_test;
         const wchar_t * giftest;
         const wchar_t * tab_main;
        }name;

        class _id{
        public:
        const static int btnSelectGif    =    65540;
        const static int btn_display    =    65541;
        const static int btn_hidetst    =    65542;
        const static int btn_lrc    =    65543;
        const static int btn_menu    =    65536;
        const static int ctrl_flash    =    65538;
        const static int gif_test    =    1000;
        const static int giftest    =    65539;
        const static int tab_main    =    65537;
        }id;

        class _string{
        public:
        const static int mccol_1    =    0;
        const static int mccol_2    =    1;
        const static int mccol_3    =    2;
        const static int mccol_4    =    3;
        const static int mccol_5    =    4;
        const static int mccol_6    =    5;
        const static int title    =    6;
        const static int ver    =    7;
        }string;

        class _color{
        public:
        const static int blue    =    0;
        const static int gray    =    1;
        const static int green    =    2;
        const static int red    =    3;
        const static int white    =    4;
        }color;

    };

     const _R R;
}

第一行保留的是一個時間戳,如果資源中布局相關的資源沒有變化,則不再生成。

首先會自動生成一個name, id映射表:SNamedID::NAMEDVALUE,這是一個結構體數組,保留每一個控件的名字及ID(自動生成的及XML中定義的,自動生成的ID自動從65536開始,因此自己定義時應該小於這個值)。

接下來定義了一個類 class _R。_R中有4個子類:_name, _id, _string, _color,每個類有一個實例,對應的名字為:name, id, string, color。

最后定義一個_R的實例R。

到這里你應該已經知道在SOUI中R這個對象有哪幾個成員了。

那么在代碼中如何使用R這個對象呢?

如何使用name對象:

觀察R這個對象,你可能已經發現,在代碼直接使用R.name.btnSelectGif就等價於在代碼中輸入L“btnSelectGif”,這樣的好處在於你在輸入R.name.btn后VS或者VA可能就給你補全后面的SelectGif,既提高了編碼效率,又保證了不會出錯。(對象name修改以后也可以使用VA的變量重命名功能自動批量修改)。

如何使用ID對象:

前面提到使用字符串來查找窗口對象相對來說較ID比較會慢一點,那么如何使用ID對象呢?要使用ID對象,有一個要求:由於自動生成的ID並沒有修改到原有的XML中,直接從XML中初始化布局時是沒有ID屬性的。為此SOUI2.0的SApplication對象增加了一個方法:InitXmlNamedID,參見demo(注意調用位置):

        //如果需要在代碼中使用R::id::namedid這種方式來使用控件必須要這一行代碼:2016年2月2日,R::id::namedXmlID是由uiresbuilder 增加-h .\res\resource.h idtable 這3個參數后生成的。
        theApp->InitXmlNamedID(namedXmlID,ARRAYSIZE(namedXmlID),TRUE);

在布局創建前給App對象初始化一個自動生成的Name轉ID表。

控件創建並初始化name屬性時,自動從該表中查詢ID。

如此,在代碼中可以直接使用R.id.btnSelectGif來查找對應的控件了。

如何使用string, color對象:

在布局XML中使用使用string, color對象和android一樣:采用@string/str-name, @color/color-name來分別引用在string,color中定義的對應的字符串或者顏色值。

這里重點講一下在代碼中使用這兩個對象:

        //演示R.color.xxx,R.string.xxx在代碼中的使用。
        COLORREF crRed = GETCOLOR(R.color.red);
        SStringW strVer = GETSTRING(R.string.ver);

上面是demo:winmain中一個使用示例。

R.color.red, R.string.ver是自動生成的兩個整數,GETCOLOR, GETSTRING這兩個宏會自動從資源中的字符串表及顏色表中獲取對應的ID指定的值。

 

啟程軟件 2016年2月22日

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM