首页 > 代码库 > 第三篇:用SOUI能做什么?

第三篇:用SOUI能做什么?

SOUI-DEMO界面预览

在回答SOUI能做什么之前,先看看SVN中demo工程的界面截图:

使用SOUI实现上面的界面主要的工作全在配置几个XML文件,基本不需要写C++代码。(如何配置XML布局将在后续文章中讲解)

从零开始生成一个使用SOUI的应用程序

以SOUI的demo为例,我们看在SOUI中如何一步一步实现一个应用程序。

首先使用Win32应用程序向导生成一个空项目。

新建一个如demo.cpp文件,定义一个_tWinMain函数。

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/){  return 0;}

在项目的包含目录中包含$(SOUIPATH)\soui\include;$(SOUIPATH)\utilities\include;这两个目录。同时在库依赖中增加soui.lib utilities.lib。

$(SOUIPATH)是从SVN签出的trunk的根目录,如果安装了soui下的应用程序向导会自动为系统增加这个环境变量。

做好上述准备工作后在工程目录下建立一个如uires的目录,用来存放程序中用到的资源文件,包括布局使用的图片及XML布局文件。

在该目录下应该至少有一个uires.idx文件。uires.idx是一个XML文件,它定义程序中用到的所有其它资源的类型及名称。

demo中使用的uires.xml如下:

 1 <?xml version="1.0" encoding="utf-8"?> 2 <resource> 3   <UIDEF> 4     <file name="xml_init" path="xml\init.xml"  /> 5   </UIDEF> 6   <ICON> 7     <file name="LOGO"  path="image\img_logo.ico" /> 8   </ICON> 9   <CURSOR>10     <file name="ANI_ARROW"  path="image\021.ani" />11     <file name="CUR_TST" path="image\camera_capture.cur"/>12   </CURSOR>13   <LAYOUT>14     <file name="maindlg" path="xml\dlg_main.xml"  />15     <file name="menu_test" path="xml\menu_test.xml"  />16     <file name="page_layout" path="xml\page_layout.xml"  />17     <file name="page_treebox" path="xml\page_treebox.xml"  />18     <file name="page_treectrl" path="xml\page_treectrl.xml"  />19     <file name="page_misc" path="xml\page_misc.xml"  />20     <file name="page_webkit" path="xml\page_webkit.xml"  />21     <file name="page_about" path="xml\page_about.xml"  />22   </LAYOUT>23   <IMGX>24     <file name="png_page_icons"   path="image\page_icons.png" />25     <file name="png_small_icons"  path="image\small_icons.png" />26 27     <file name="webbtn_back"  path="image\webbtn_back.png" />28     <file name="webbtn_forward"  path="image\webbtn_forward.png" />29     <file name="webbtn_refresh"  path="image\webbtn_refresh.png" />30     31     <file name="png_treeicon"             path="image\TreeIcon.png"/>32     <file name="png_menu_border"  path="image\menuborder.png" />33 34     <file name="png_vscroll"  path="image\vscrollbar.png" />35     36     <file name="png_tab_left"  path="image\tab_left.png" />37     <file name="png_tab_left_splitter"  path="image\tab_left_splitter.png" />38     <file name="png_tab_main"  path="image\tab_main.png" />39     <file name="btn_menu" path="image\btn_menu.png"  />40   </IMGX>41   <GIF>42     <file name="gif_horse"    path="image\horse.gif"/>43     <file name="gif_penguin"    path="image\penguin.gif"/>44   </GIF>45   <rtf>46     <file name="rtf_test"    path="rtf\RTF测试.rtf"/>47   </rtf>48   <script>49     <file name="lua_test" path="lua\test.lua"/>50   </script>51   <translator>52     <file name="lang_cn" path="translation files\lang_cn.xml"/>53   </translator>54 </resource>

如上所示,该XML有一个resource的根节点,下面可以是任意定义的类型(ICON, BITMAP,CURSOR除外,它们是预定义的类型,不能修改类型名)。

每个类型下面定义有file元素,元素中有两个属性:name 及 path。

name即资源的名称,path即资源的路径。所有资源建议采用相对路径,即相对于uires.idx文件的路径。

在程序中通过type及name来引用资源。

 

下面开始填空:

  1 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)  2 {  3     //必须要调用OleInitialize来初始化运行环境  4     HRESULT hRes = OleInitialize(NULL);  5     SASSERT(SUCCEEDED(hRes));  6       7     int nRet = 0;   8   9     //定义一组组件加载辅助对象 10     //SComLoader实现从DLL的指定函数创建符号SOUI要求的类COM组件。 11     SComLoader imgDecLoader; 12     SComLoader renderLoader; 13     SComLoader transLoader; 14     SComLoader scriptLoader; 15     SComLoader zipResLoader; 16      17     //将程序的运行路径修改到demo所在的目录 18     TCHAR szCurrentDir[MAX_PATH]={0}; 19     GetModuleFileName( NULL, szCurrentDir, sizeof(szCurrentDir) ); 20     LPTSTR lpInsertPos = _tcsrchr( szCurrentDir, _T(\\) ); 21     _tcscpy(lpInsertPos,_T("\\..\\demo")); 22     SetCurrentDirectory(szCurrentDir); 23      24     { 25         //定义一组类SOUI系统中使用的类COM组件 26         //CAutoRefPtr是一个SOUI系统中使用的智能指针类 27         CAutoRefPtr<IImgDecoderFactory> pImgDecoderFactory; //图片解码器,由imagedecoder-wid.dll模块提供 28         CAutoRefPtr<IRenderFactory> pRenderFactory;         //UI渲染模块,由render-gdi.dll或者render-skia.dll提供 29         CAutoRefPtr<ITranslatorMgr> trans;                  //多语言翻译模块,由translator.dll提供 30         CAutoRefPtr<IScriptModule> pScriptLua;              //lua脚本模块,由scriptmodule-lua.dll提供 31          32         BOOL bLoaded=FALSE; 33         int nType=MessageBox(GetActiveWindow(),_T("选择渲染类型:\n[yes]: Skia\n[no]:GDI\n[cancel]:Quit"),_T("select a render"),MB_ICONQUESTION|MB_YESNOCANCEL); 34         if(nType == IDCANCEL) return -1; 35         //从各组件中显示创建上述组件对象 36         bLoaded=renderLoader.CreateInstance(nType==IDYES?COM_RENDER_SKIA:COM_RENDER_GDI,(IObjRef**)&pRenderFactory); 37         SASSERT_FMT(bLoaded,_T("load module [%s] failed!"),nType==IDYES?COM_RENDER_SKIA:COM_RENDER_GDI); 38         bLoaded=imgDecLoader.CreateInstance(COM_IMGDECODER,(IObjRef**)&pImgDecoderFactory); 39         SASSERT_FMT(bLoaded,_T("load module [%s] failed!"),COM_IMGDECODER); 40         bLoaded=transLoader.CreateInstance(COM_TRANSLATOR,(IObjRef**)&trans); 41         SASSERT_FMT(bLoaded,_T("load module [%s] failed!"),COM_TRANSLATOR); 42         //为渲染模块设置它需要引用的图片解码模块 43         pRenderFactory->SetImgDecoderFactory(pImgDecoderFactory); 44         //定义一个唯一的SApplication对象,SApplication管理整个应用程序的资源 45         SApplication *theApp=new SApplication(pRenderFactory,hInstance); 46  47         //定义一人个资源提供对象,SOUI系统中实现了3种资源加载方式,分别是从文件加载,从EXE的资源加载及从ZIP压缩包加载 48         CAutoRefPtr<IResProvider>   pResProvider; 49 #if (RES_TYPE == 0)//从文件加载 50         CreateResProvider(RES_FILE,(IObjRef**)&pResProvider); 51         if(!pResProvider->Init((LPARAM)_T("uires"),0)) 52         { 53             SASSERT(0); 54             return 1; 55         } 56 #elif (RES_TYPE==1)//从EXE资源加载 57         CreateResProvider(RES_PE,(IObjRef**)&pResProvider); 58         pResProvider->Init((WPARAM)hInstance,0); 59 #elif (RES_TYPE==2)//从ZIP包加载 60         bLoaded=zipResLoader.CreateInstance(COM_ZIPRESPROVIDER,(IObjRef**)&pResProvider); 61         SASSERT(bLoaded); 62         ZIPRES_PARAM param; 63         param.ZipFile(pRenderFactory, _T("uires.zip")); 64         bLoaded = pResProvider->Init((WPARAM)&param,0); 65         SASSERT(bLoaded); 66 #endif 67         //将创建的IResProvider交给SApplication对象 68         theApp->AddResProvider(pResProvider); 69  70         if(trans) 71         {//加载语言翻译包 72             theApp->SetTranslator(trans); 73             pugi::xml_document xmlLang; 74             if(theApp->LoadXmlDocment(xmlLang,_T("lang_cn"),_T("translator"))) 75             { 76                 CAutoRefPtr<ITranslator> langCN; 77                 trans->CreateTranslator(&langCN); 78                 langCN->Load(&xmlLang.child(L"language"),1);//1=LD_XML 79                 trans->InstallTranslator(langCN); 80             } 81         } 82 #ifdef DLL_SOUI 83         //加载LUA脚本模块,注意,脚本模块只有在SOUI内核是以DLL方式编译时才能使用。 84         bLoaded=scriptLoader.CreateInstance(COM_SCRIPT_LUA,(IObjRef**)&pScriptLua); 85         SASSERT_FMT(bLoaded,_T("load module [%s] failed!"),COM_SCRIPT_LUA); 86         if(pScriptLua) 87         { 88             theApp->SetScriptModule(pScriptLua); 89             size_t sz=pResProvider->GetRawBufferSize(_T("script"),_T("lua_test")); 90             if(sz) 91             { 92                 CMyBuffer<char> lua; 93                 lua.Allocate(sz); 94                 pResProvider->GetRawBuffer(_T("script"),_T("lua_test"),lua,sz); 95                 pScriptLua->executeScriptBuffer(lua,sz); 96             } 97         } 98 #endif//DLL_SOUI 99 100         //向SApplication系统中注册由外部扩展的控件及SkinObj类101         SWkeLoader wkeLoader;102         if(wkeLoader.Init(_T("wke.dll")))        103         {104             theApp->RegisterWndFactory(TplSWindowFactory<SWkeWebkit>());//注册WKE浏览器105         }106         theApp->RegisterWndFactory(TplSWindowFactory<SGifPlayer>());//注册GIFPlayer107         theApp->RegisterSkinFactory(TplSkinFactory<SSkinGif>());//注册SkinGif108         SSkinGif::Gdiplus_Startup();109         110         //加载系统资源111         HMODULE hSysResource=LoadLibrary(SYS_NAMED_RESOURCE);112         if(hSysResource)113         {114             CAutoRefPtr<IResProvider> sysSesProvider;115             CreateResProvider(RES_PE,(IObjRef**)&sysSesProvider);116             sysSesProvider->Init((WPARAM)hSysResource,0);117             theApp->LoadSystemNamedResource(sysSesProvider);118         }119 120         //加载全局资源描述XML121         theApp->Init(_T("xml_init")); 122 123         {124             //创建并显示使用SOUI布局应用程序窗口,为了保存窗口对象的析构先于其它对象,把它们缩进一层。125             CMainDlg dlgMain;  126             dlgMain.Create(GetActiveWindow(),0,0,800,600);127             dlgMain.GetNative()->SendMessage(WM_INITDIALOG);128             dlgMain.CenterWindow();129             dlgMain.ShowWindow(SW_SHOWNORMAL);130             nRet=theApp->Run(dlgMain.m_hWnd);131         }132         133         //应用程序退出134         delete theApp; 135         SSkinGif::Gdiplus_Shutdown();136 137     }138 139     OleUninitialize();140     return nRet;141 }

大家可能发现使用SOUI的这个main函数相对于其它程序可能要更加复杂,这是为了达到程序配置的灵活性需要付出的代价。

好在SOUI提供了应用程序向导,它会帮助你点两个按钮就生成一整套框架。

SOUI与其它应用程序开发框架

SOUI是一个使用纯Win32 SDK开发的UI库,内核部分使用了pugixml这个第三方库作为XML解析的模块,除此之外,不再依赖其它第三方库,同时所有使用的模块都可以通过源代码编译。

SOUI提供了一整套完整的UI开发框架,不需要依赖其它的如MFC,WTL等开发框架。同时由于SOUI是纯win32的SDK开发的,它理论上也可以和任意的其它开发框架共存。(实际处理中由于SOUI中使用的一些类的命名可能和其它框架冲突,因此可能需要注意命名空间的使用。)