從0開始一個SOUI項目
1、環境配置
SOUI項目本質是一個基於Win32窗口的應用程序。因此首先我們可以從Win32窗口應用程序向導創建一個簡單的Win32項目。
並在第3頁選擇“Window應用程序”
選擇“完成”后生成一個Win32應用程序骨架。
項目的文件結構如下圖:
要使用SOUI開發程序程序,首先當然是要找到從SVN獲取的SOUI項目代碼。假定SOUI項目保存在%SOUIPATH%這個環境變量指向的目錄(安裝了SOUI向導后會自動創建這個環境變量)。
我們需要在VS的include目錄中增加兩個目錄:
"$(SOUIPATH)/soui/include";"$(SOUIPATH)/utilities/include"
如圖:
注:新版本還需要增加一個包含目錄:$(SOUIPATH)/config
假定你已經編譯好了SOUI內核代碼,默認情況下內核庫會生成在$(SOUIPATH)/bin目錄下,我們還需要在引用的庫中指定兩個庫文件:souid.lib,utilitiesd.lib(以debug版本為例)。
設置好項目后,默認情況下還需要把編譯選項中的“代碼生成”從MDd修改為MTd,並把“將wchar_t視為內置類型”修改為“否”。(因為這是SOUI的默認編譯配置)
到這里環境配置基本完成。
2、准備資源
到這里准備工作還沒有完,我們需要為SOUI准備一套程序資源,並把它放到項目目錄下。
最基本的資源至少應該包括:
uires.idx:定義資源索引
init.xml:定義全局UI的屬性,包含字體,字符串表,skin,style,objattr,參見前篇介紹。
dlg_main.xml:主窗口而已XML。
init.xml和dlg_main.xml的文件名不限,但是uires.idx的文件名是固定的。
uires.idx:
<resource> <UIDEF> <file name="XML_INIT" path="xml\init.xml" /> </UIDEF> <LAYOUT> <file name="XML_MAINWND" path="xml\dlg_main.xml" /> </LAYOUT> </resource>
init.xml:
<?xml version="1.0" encoding="utf-8"?> <UIDEF> <font face="宋體" size="15"/> <string> <title value=""/> <ver value="1.0"/> </string> <skin> </skin> <style> <class name="normalbtn" font="" colorText="#385e8b" colorTextDisable="#91a7c0" textMode="25" cursor="hand" margin-x="0"/> </style> <objattr> </objattr> </UIDEF>
dlg_main.xml:
<SOUI name="mainWindow" title="%title% ver:%ver%" width="600" height="400" appWnd="1" margin="20,5,5,5" resizable="1" translucent="1" > <root skin="_skin.sys.wnd.bkgnd"> <caption pos="0,0,-0,30"> <text pos="11,9">%title% ver:%ver%</text> <imgbtn name="btn_close" skin="_skin.sys.btn.close" pos="-45,0" tip="close" animate="1"/> <imgbtn name="btn_max" skin="_skin.sys.btn.maximize" pos="-83,0" animate="1" /> <imgbtn name="btn_restore" skin="_skin.sys.btn.restore" pos="-83,0" show="0" animate="1" /> <imgbtn name="btn_min" skin="_skin.sys.btn.minimize" pos="-121,0" animate="1" /> </caption> <window pos="5,30,-5,-5"> <text pos="|0,|0" pos2type="center" colorText="#ff0000">Hellow World! UI? Just so so!</text> <button class ="normalbtn" pos="|-50,[20,@100,@30" name="btn_msgbox">show msg box</button> </window> </root> </SOUI>
如果對UI布局不明白可以參考“第五篇”。
3、開始編碼
要開始編寫代碼還需要修改一下stdafx.h如下:
// stdafx.h : 標准系統包含文件的包含文件,
// 或是經常使用但不常更改的
// 特定於項目的包含文件
//
#pragma once
#include "targetver.h"
#define _CRT_SECURE_NO_WARNINGS
#define DLL_SOUI //SOUI是以DLL提供時需要定義這個宏 #include <souistd.h> #include <core/SHostDialog.h> #include <control/SMessageBox.h> #include <control/souictrls.h> using namespace SOUI;
功能就是引用幾個SOUI頭文件。
打開helloworld.cpp,刪除文件中除空main函數以外的全部代碼,剩下的代碼如下:
// hellowworld.cpp : 定義應用程序的入口點。
//
#include "stdafx.h" #include "hellowworld.h" int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { return 0; }
這是一個可以編譯的空項目。
4、開始填充Main程序框架
// helloworld.cpp : main source file // #include "stdafx.h" #include <com-loader.hpp> #ifdef _DEBUG #define COM_IMGDECODER _T("imgdecoder-wicd.dll") #define COM_RENDER_GDI _T("render-gdid.dll") #define SYS_NAMED_RESOURCE _T("soui-sys-resourced.dll") #else #define COM_IMGDECODER _T("imgdecoder-wic.dll") #define COM_RENDER_GDI _T("render-gdi.dll") #define SYS_NAMED_RESOURCE _T("soui-sys-resource.dll") #endif int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/) { HRESULT hRes = OleInitialize(NULL); SASSERT(SUCCEEDED(hRes)); int nRet = 0; SComLoader imgDecLoader; SComLoader renderLoader; SComLoader transLoader; //將程序的運行路徑修改到項目所在目錄所在的目錄 TCHAR szCurrentDir[MAX_PATH]={0}; GetModuleFileName( NULL, szCurrentDir, sizeof(szCurrentDir) ); LPTSTR lpInsertPos = _tcsrchr( szCurrentDir, _T('\\') ); _tcscpy(lpInsertPos+1,_T("..")); SetCurrentDirectory(szCurrentDir); { CAutoRefPtr<SOUI::IImgDecoderFactory> pImgDecoderFactory; CAutoRefPtr<SOUI::IRenderFactory> pRenderFactory; imgDecLoader.CreateInstance(COM_IMGDECODER,(IObjRef**)&pImgDecoderFactory); renderLoader.CreateInstance(COM_RENDER_GDI,(IObjRef**)&pRenderFactory); pRenderFactory->SetImgDecoderFactory(pImgDecoderFactory); SApplication *theApp=new SApplication(pRenderFactory,hInstance); HMODULE hSysResource=LoadLibrary(SYS_NAMED_RESOURCE); if(hSysResource) { CAutoRefPtr<IResProvider> sysSesProvider; CreateResProvider(RES_PE,(IObjRef**)&sysSesProvider); sysSesProvider->Init((WPARAM)hSysResource,0); theApp->LoadSystemNamedResource(sysSesProvider); } CAutoRefPtr<IResProvider> pResProvider; CreateResProvider(RES_FILE,(IObjRef**)&pResProvider); if(!pResProvider->Init((LPARAM)_T("uires"),0)) { SASSERT(0); return 1; } theApp->AddResProvider(pResProvider);
//2.x版本已經不需要下面這行。 //theApp->Init(_T("XML_INIT")); {//在這里加入主窗口運行代碼 } delete theApp; } OleUninitialize(); return nRet; }
將helloworld.cpp修改如上。
這里主要功能是配置幾個SOUI需要的組件。
5、為主窗口布局生成一個C++類
和MFC,WTL等一樣,SOUI可以有兩種方式顯示窗口:模態與非模態。
這里我們采用非模態窗口來演示。
因此我們需要從SHostWnd派生出一個C++對象:CMainWnd
// MainWnd.h : interface of the CMainWnd class // ///////////////////////////////////////////////////////////////////////////// #pragma once class CMainWnd : public SHostWnd { public: CMainWnd() : SHostWnd(_T("LAYOUT:XML_MAINWND"))//這里定義主界面需要使用的布局文件 { m_bLayoutInited=FALSE; } void OnClose() { PostMessage(WM_QUIT); } void OnMaximize() { SendMessage(WM_SYSCOMMAND,SC_MAXIMIZE); } void OnRestore() { SendMessage(WM_SYSCOMMAND,SC_RESTORE); } void OnMinimize() { SendMessage(WM_SYSCOMMAND,SC_MINIMIZE); } void OnSize(UINT nType, CSize size) { SetMsgHandled(FALSE); if(!m_bLayoutInited) return; if(nType==SIZE_MAXIMIZED) { FindChildByName(L"btn_restore")->SetVisible(TRUE); FindChildByName(L"btn_max")->SetVisible(FALSE); }else if(nType==SIZE_RESTORED) { FindChildByName(L"btn_restore")->SetVisible(FALSE); FindChildByName(L"btn_max")->SetVisible(TRUE); } } void OnBtnMsgBox() { SMessageBox(NULL,_T("this is a message box"),_T("haha"),MB_OK|MB_ICONEXCLAMATION); SMessageBox(NULL,_T("this message box includes two buttons"),_T("haha"),MB_YESNO|MB_ICONQUESTION); SMessageBox(NULL,_T("this message box includes three buttons"),NULL,MB_ABORTRETRYIGNORE); } BOOL OnInitDialog( HWND hWnd, LPARAM lParam ) { m_bLayoutInited=TRUE; return 0; } protected: //按鈕事件處理映射表 EVENT_MAP_BEGIN() EVENT_NAME_COMMAND(L"btn_close",OnClose) EVENT_NAME_COMMAND(L"btn_min",OnMinimize) EVENT_NAME_COMMAND(L"btn_max",OnMaximize) EVENT_NAME_COMMAND(L"btn_restore",OnRestore) EVENT_NAME_COMMAND(L"btn_msgbox",OnBtnMsgBox) EVENT_MAP_END() //窗口消息處理映射表 BEGIN_MSG_MAP_EX(CMainWnd) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CLOSE(OnClose) MSG_WM_SIZE(OnSize) CHAIN_MSG_MAP(SHostWnd)//注意將沒有處理的消息交給基類處理 REFLECT_NOTIFICATIONS_EX() END_MSG_MAP() private: BOOL m_bLayoutInited; };
為了介紹方便,這個窗口類所有代碼都在這個mainwnd.h文件里。
6、再進一步填充main函數
{ //在這里加入主窗口運行代碼 CMainWnd wndMain; wndMain.Create(GetActiveWindow(),0,0,800,600); wndMain.SendMessage(WM_INITDIALOG); wndMain.CenterWindow(wndMain.m_hWnd); wndMain.ShowWindow(SW_SHOWNORMAL); nRet=theApp->Run(wndMain.m_hWnd); //程序結束 }
當然main前面還要有一行:#include "mainwnd.h"
大功造成!
7、編譯運行結果
認識SOUI應用程序向導
開發一個使用SOUI的應用程序,如果從Win32項目類型開始,即便是我對SOUI這樣了如指掌,也至少要10分鍾以上才能配置出一個使用SOUI的開發環境。
為了幫助程序員從簡單的重復勞動解脫出來,也幫助初學都快速開始,我特別為SOUI制作了一個適用於VS各版本的應用程序向導。
使用向導可以通過簡單的選擇兩個選項就自動完全項目配置,編譯即可看到UI布局結果。
1、SOUI向導的安裝
在SOUI項目下有一個wizard目錄,運行目錄下的wizard.setup.exe會顯示下面界面:
選擇一個系統中安裝的VS版本,點擊安裝就會向該版本中安裝SOUI向導。
安裝成功后顯示:
注:原來DuiEngine的向導安裝程序運行后設置的環境變量經常要重啟系統才生效,SOUI中的版本已經經過優化,基本上不需要重啟系統,但已經打開的VS肯定是沒有新增加的環境變量的。
2、使用向導創建SOUI應用程序
向導安裝完成后,打開VS的新建項目窗口,會在“Virtual C++”下找到SOUI向導入口。
輸入項目名稱后點擊確定打開SOUI向導頁(只有一頁)
點擊完成即可開始享受最簡單高效的界面編程了。
注:由於SOUI還在持續更新,上述手動創建helloWorld的代碼有可能在新版本中失效。請以向導創建的代碼為准!!!
下一篇介紹SOUI中控件事件響應。