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日