在回答SOUI能做什么之前,先看看SVN中demo工程的界面截图:
使用SOUI实现上面的界面主要的工作全在配置几个XML文件,基本不需要写C++代码。(如何配置XML布局将在后续文章中讲解)
以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)¶m,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>());//注册GIFPlayer 107 theApp->RegisterSkinFactory(TplSkinFactory<SSkinGif>());//注册SkinGif 108 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 //加载全局资源描述XML 121 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 }
main中用到一个类CMainDlg,该类是demo的主窗口,前面提供的界面截图都是由该类渲染出来。
下面我们看一下CMainDlg的实现:
maindlg.h
1 /** 2 * Copyright (C) 2014-2050 3 * All rights reserved. 4 * 5 * @file MainDlg.h 6 * @brief 7 * @version v1.0 8 * @author SOUI group 9 * @date 2014/08/15 10 * 11 * Describe 主窗口实现 12 */ 13 14 #pragma once 15 16 /** 17 * @class CMainDlg 18 * @brief 主窗口实现 19 * 20 * Describe 非模式窗口从SHostWnd派生,模式窗口从SHostDialog派生 21 */ 22 class CMainDlg : public SHostWnd 23 { 24 public: 25 26 /** 27 * CMainDlg 28 * @brief 构造函数 29 * Describe 使用uires.idx中定义的maindlg对应的xml布局创建UI 30 */ 31 CMainDlg() : SHostWnd(_T("maindlg")),m_bLayoutInited(FALSE) 32 { 33 } 34 35 protected: 36 ////////////////////////////////////////////////////////////////////////// 37 // Window消息响应函数 38 LRESULT OnInitDialog(HWND hWnd, LPARAM lParam); 39 void OnDestory(); 40 41 void OnClose() 42 { 43 AnimateHostWindow(200,AW_CENTER|AW_HIDE); 44 PostMessage(WM_QUIT); 45 } 46 void OnMaximize() 47 { 48 GetNative()->SendMessage(WM_SYSCOMMAND,SC_MAXIMIZE); 49 } 50 void OnRestore() 51 { 52 GetNative()->SendMessage(WM_SYSCOMMAND,SC_RESTORE); 53 } 54 void OnMinimize() 55 { 56 GetNative()->SendMessage(WM_SYSCOMMAND,SC_MINIMIZE); 57 } 58 59 void OnSize(UINT nType, CSize size) 60 { 61 SetMsgHandled(FALSE); //这一行很重要,保证消息继续传递给SHostWnd处理,当然也可以用SHostWnd::OnSize(nType,size);代替,但是这里使用的方法更简单,通用 62 if(!m_bLayoutInited) return; 63 if(nType==SIZE_MAXIMIZED) 64 { 65 FindChildByID(3)->SetVisible(TRUE); 66 FindChildByID(2)->SetVisible(FALSE); 67 }else if(nType==SIZE_RESTORED) 68 { 69 FindChildByID(3)->SetVisible(FALSE); 70 FindChildByID(2)->SetVisible(TRUE); 71 } 72 } 73 74 int OnCreate(LPCREATESTRUCT lpCreateStruct); 75 void OnShowWindow(BOOL bShow, UINT nStatus); 76 77 //DUI菜单响应函数 78 void OnCommand(UINT uNotifyCode, int nID, HWND wndCtl); 79 80 protected: 81 ////////////////////////////////////////////////////////////////////////// 82 // SOUI事件处理函数 83 //演示屏蔽指定edit控件的右键菜单 84 BOOL OnEditMenu(CPoint pt) 85 { 86 return TRUE; 87 } 88 89 //按钮控件的响应 90 void OnBtnSelectGIF(); 91 void OnBtnMenu(); 92 void OnBtnInsertGif2RE(); 93 void OnBtnHideTest(); 94 void OnBtnMsgBox(); 95 96 void OnBtnWebkitGo(); 97 void OnBtnWebkitBackward(); 98 void OnBtnWebkitForeward(); 99 void OnBtnWebkitRefresh(); 100 101 //演示如何使用subscribeEvent来不使用事件映射表实现事件响应 102 bool OnListHeaderClick(EventArgs *pEvt); 103 104 //UI控件的事件及响应函数映射表 105 EVENT_MAP_BEGIN() 106 EVENT_ID_COMMAND(1, OnClose) 107 EVENT_ID_COMMAND(2, OnMaximize) 108 EVENT_ID_COMMAND(3, OnRestore) 109 EVENT_ID_COMMAND(5, OnMinimize) 110 EVENT_NAME_CONTEXTMENU(L"edit_1140",OnEditMenu) 111 EVENT_NAME_COMMAND(L"btn_msgbox",OnBtnMsgBox) 112 EVENT_NAME_COMMAND(L"btnSelectGif",OnBtnSelectGIF) 113 EVENT_NAME_COMMAND(L"btn_menu",OnBtnMenu) 114 EVENT_NAME_COMMAND(L"btn_webkit_go",OnBtnWebkitGo) 115 EVENT_NAME_COMMAND(L"btn_webkit_back",OnBtnWebkitBackward) 116 EVENT_NAME_COMMAND(L"btn_webkit_fore",OnBtnWebkitForeward) 117 EVENT_NAME_COMMAND(L"btn_webkit_refresh",OnBtnWebkitRefresh) 118 EVENT_NAME_COMMAND(L"btn_hidetst",OnBtnHideTest) 119 EVENT_NAME_COMMAND(L"btn_insert_gif",OnBtnInsertGif2RE) 120 EVENT_MAP_END() 121 122 //HOST消息及响应函数映射表 123 BEGIN_MSG_MAP_EX(CMainDlg) 124 MSG_WM_CREATE(OnCreate) 125 MSG_WM_INITDIALOG(OnInitDialog) 126 MSG_WM_DESTROY(OnDestory) 127 MSG_WM_CLOSE(OnClose) 128 MSG_WM_SIZE(OnSize) 129 MSG_WM_COMMAND(OnCommand) 130 MSG_WM_SHOWWINDOW(OnShowWindow) 131 CHAIN_MSG_MAP(SHostWnd) 132 REFLECT_NOTIFICATIONS_EX() 133 END_MSG_MAP() 134 135 protected: 136 ////////////////////////////////////////////////////////////////////////// 137 // 辅助函数 138 void InitListCtrl(); 139 private: 140 BOOL m_bLayoutInited;/**<UI完成布局标志 */ 141 };
maindlg.cpp
1 // MainDlg.cpp : implementation of the CMainDlg class 2 // 3 ///////////////////////////////////////////////////////////////////////////// 4 5 #include "stdafx.h" 6 #include "MainDlg.h" 7 #include "helper/SMenu.h" 8 #include "../controls.extend/FileHelper.h" 9 10 #include <dwmapi.h> 11 #pragma comment(lib,"dwmapi.lib") 12 13 14 15 int CMainDlg::OnCreate( LPCREATESTRUCT lpCreateStruct ) 16 { 17 // MARGINS mar = {5,5,30,5}; 18 // DwmExtendFrameIntoClientArea ( m_hWnd, &mar );//打开这里可以启用Aero效果 19 SetMsgHandled(FALSE); 20 return 0; 21 } 22 23 void CMainDlg::OnShowWindow( BOOL bShow, UINT nStatus ) 24 { 25 if(bShow) 26 { 27 AnimateHostWindow(200,AW_CENTER); 28 } 29 } 30 31 struct student{ 32 TCHAR szName[100]; 33 TCHAR szSex[10]; 34 int age; 35 int score; 36 }; 37 38 //init listctrl 39 void CMainDlg::InitListCtrl() 40 { 41 SListCtrl *pList=FindChildByName2<SListCtrl>(L"lc_test"); 42 if(pList) 43 { 44 SWindow *pHeader=pList->GetWindow(GSW_FIRSTCHILD); 45 pHeader->GetEventSet()->subscribeEvent(EVT_HEADER_CLICK,Subscriber(&CMainDlg::OnListHeaderClick,this)); 46 47 TCHAR szSex[][5]={_T("男"),_T("女"),_T("人妖")}; 48 for(int i=0;i<100;i++) 49 { 50 student *pst=new student; 51 _stprintf(pst->szName,_T("学生_%d"),i+1); 52 _tcscpy(pst->szSex,szSex[rand()%3]); 53 pst->age=rand()%30; 54 pst->score=rand()%60+40; 55 56 int iItem=pList->InsertItem(i,pst->szName); 57 pList->SetItemData(iItem,(DWORD)pst); 58 pList->SetSubItemText(iItem,1,pst->szSex); 59 TCHAR szBuf[10]; 60 _stprintf(szBuf,_T("%d"),pst->age); 61 pList->SetSubItemText(iItem,2,szBuf); 62 _stprintf(szBuf,_T("%d"),pst->score); 63 pList->SetSubItemText(iItem,3,szBuf); 64 } 65 } 66 } 67 68 int funCmpare(void* pCtx,const void *p1,const void *p2) 69 { 70 int iCol=*(int*)pCtx; 71 72 const DXLVITEM *plv1=(const DXLVITEM*)p1; 73 const DXLVITEM *plv2=(const DXLVITEM*)p2; 74 75 const student *pst1=(const student *)plv1->dwData; 76 const student *pst2=(const student *)plv2->dwData; 77 78 switch(iCol) 79 { 80 case 0://name 81 return _tcscmp(pst1->szName,pst2->szName); 82 case 1://sex 83 return _tcscmp(pst1->szSex,pst2->szSex); 84 case 2://age 85 return pst1->age-pst2->age; 86 case 3://score 87 return pst1->score-pst2->score; 88 default: 89 return 0; 90 } 91 } 92 93 bool CMainDlg::OnListHeaderClick(EventArgs *pEvtBase) 94 { 95 EventHeaderClick *pEvt =(EventHeaderClick*)pEvtBase; 96 SHeaderCtrl *pHeader=(SHeaderCtrl*)pEvt->sender; 97 SListCtrl *pList=FindChildByName2<SListCtrl>(L"lc_test"); 98 99 SHDITEM hditem; 100 hditem.mask=SHDI_ORDER; 101 pHeader->GetItem(pEvt->iItem,&hditem); 102 pList->SortItems(funCmpare,&hditem.iOrder); 103 return true; 104 } 105 106 void CMainDlg::OnDestory() 107 { 108 SListCtrl *pList=FindChildByName2<SListCtrl>(L"lc_test"); 109 if(pList) 110 { 111 for(int i=0;i<pList->GetItemCount();i++) 112 { 113 student *pst=(student*) pList->GetItemData(i); 114 delete pst; 115 } 116 } 117 SetMsgHandled(FALSE); 118 } 119 120 121 LRESULT CMainDlg::OnInitDialog( HWND hWnd, LPARAM lParam ) 122 { 123 m_bLayoutInited=TRUE; 124 InitListCtrl(); 125 126 #ifdef DLL_SOUI 127 SWindow *pTst=FindChildByName(L"btn_tstevt"); 128 if(pTst) SApplication::getSingleton().GetScriptModule()->subscribeEvent(pTst,EVT_CMD,"onEvtTstClick"); 129 #endif 130 131 return 0; 132 } 133 134 void CMainDlg::OnBtnWebkitGo() 135 { 136 SWkeWebkit *pWebkit= FindChildByName2<SWkeWebkit>(L"wke_test"); 137 if(pWebkit) 138 { 139 SEdit *pEdit=FindChildByName2<SEdit>(L"edit_url"); 140 SStringW strUrl=pEdit->GetWindowText(); 141 pWebkit->SetAttribute(L"url",strUrl,FALSE); 142 } 143 } 144 145 void CMainDlg::OnBtnWebkitBackward() 146 { 147 SWkeWebkit *pWebkit= FindChildByName2<SWkeWebkit>(L"wke_test"); 148 if(pWebkit) 149 { 150 pWebkit->GetWebView()->goBack(); 151 } 152 } 153 154 void CMainDlg::OnBtnWebkitForeward() 155 { 156 SWkeWebkit *pWebkit= FindChildByName2<SWkeWebkit>(L"wke_test"); 157 if(pWebkit) 158 { 159 pWebkit->GetWebView()->goForward(); 160 } 161 } 162 163 void CMainDlg::OnBtnWebkitRefresh() 164 { 165 SWkeWebkit *pWebkit= FindChildByName2<SWkeWebkit>(L"wke_test"); 166 if(pWebkit) 167 { 168 pWebkit->GetWebView()->reload(); 169 } 170 } 171 172 void CMainDlg::OnBtnSelectGIF() 173 { 174 SGifPlayer *pGifPlayer = FindChildByName2<SGifPlayer>(L"giftest"); 175 if(pGifPlayer) 176 { 177 CFileDialogEx openDlg(TRUE,_T("gif"),0,6,_T("gif files(*.gif)\0*.gif\0All files (*.*)\0*.*\0\0")); 178 if(openDlg.DoModal()==IDOK) 179 pGifPlayer->PlayGifFile(openDlg.m_szFileName); 180 } 181 } 182 183 void CMainDlg::OnBtnMenu() 184 { 185 SMenu menu; 186 menu.LoadMenu(_T("menu_test"),_T("LAYOUT")); 187 POINT pt; 188 GetCursorPos(&pt); 189 menu.TrackPopupMenu(0,pt.x,pt.y,m_hWnd); 190 } 191 192 //演示如何响应菜单事件 193 void CMainDlg::OnCommand( UINT uNotifyCode, int nID, HWND wndCtl ) 194 { 195 if(uNotifyCode==0) 196 { 197 if(nID==6) 198 {//nID==6对应menu_test定义的菜单的exit项。 199 PostMessage(WM_CLOSE); 200 }else if(nID==54) 201 {//about SOUI 202 STabCtrl *pTabCtrl = FindChildByName2<STabCtrl>(L"tab_main"); 203 if(pTabCtrl) pTabCtrl->SetCurSel(_T("about")); 204 } 205 } 206 } 207 208 void CMainDlg::OnBtnHideTest() 209 { 210 SWindow * pBtn = FindChildByName(L"btn_hidetst"); 211 if(pBtn) pBtn->SetVisible(FALSE,TRUE); 212 } 213 214 #include "skinole\ImageOle.h" 215 216 void CMainDlg::OnBtnInsertGif2RE() 217 { 218 SRichEdit *pEdit = FindChildByName2<SRichEdit>(L"re_gifhost"); 219 if(pEdit) 220 { 221 ISkinObj * pSkin = GETSKIN(L"gif_penguin"); 222 if(pSkin) 223 { 224 RichEdit_InsertSkin(pEdit,pSkin); 225 } 226 } 227 } 228 229 void CMainDlg::OnBtnMsgBox() 230 { 231 SMessageBox(NULL,_T("this is a message box"),_T("haha"),MB_OK|MB_ICONEXCLAMATION); 232 SMessageBox(NULL,_T("this message box includes two buttons"),_T("haha"),MB_YESNO|MB_ICONQUESTION); 233 SMessageBox(NULL,_T("this message box includes three buttons"),NULL,MB_ABORTRETRYIGNORE); 234 }
maindlg.cpp的主要工作就是调用SHostWnd的FindChildByName/FindChildByID查找到SOUI的控件,然后调用控件提供的方法完成对控件的操作。
大家可能发现使用SOUI的这个main函数相对于其它程序可能要更加复杂,这是为了达到程序配置的灵活性需要付出的代价。
好在SOUI提供了应用程序向导,它会帮助你点两个按钮就生成一整套框架。
SOUI是一个使用纯Win32 SDK开发的UI库,内核部分使用了pugixml这个第三方库作为XML解析的模块,除此之外,不再依赖其它第三方库,同时所有使用的模块都可以通过源代码编译。
SOUI提供了一整套完整的UI开发框架,不需要依赖其它的如MFC,WTL等开发框架。同时由于SOUI是纯win32的SDK开发的,它理论上也可以和任意的其它开发框架共存。(实际处理中由于SOUI中使用的一些类的命名可能和其它框架冲突,因此可能需要注意命名空间的使用。)