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)¶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與其它應用程序開發框架
SOUI是一個使用純Win32 SDK開發的UI庫,內核部分使用了pugixml這個第三方庫作為XML解析的模塊,除此之外,不再依賴其它第三方庫,同時所有使用的模塊都可以通過源代碼編譯。
SOUI提供了一整套完整的UI開發框架,不需要依賴其它的如MFC,WTL等開發框架。同時由於SOUI是純win32的SDK開發的,它理論上也可以和任意的其它開發框架共存。(實際處理中由於SOUI中使用的一些類的命名可能和其它框架沖突,因此可能需要注意命名空間的使用。)